Version: 0.1 / 5.40.2

This commit is contained in:
DavidXanatos 2020-06-01 18:11:56 +02:00 committed by xanatosdavid@gmail.com
parent e9d144b696
commit e30709310e
148 changed files with 13666 additions and 239 deletions

View File

@ -2,6 +2,21 @@
All notable changes to this project will be documented in this file.
This project adheres to [Semantic Versioning](http://semver.org/).
## [1.0.1 / 5.40.2] - 2020-06-01
### Added
- Created a new Qt based UI names SandMan (Sandboxie Manager)
- Resource monitor now shows the PID
- Added basic API call log using updated BSA LogApiDll
### Changed
- reworked resource monitor to work with multiple event consumers
- reworked log to work with multiple event consumers
## [5.40.1] - 2020-04-10
### Added

View File

@ -1,7 +1,7 @@

Microsoft Visual Studio Solution File, Format Version 12.00
# Visual Studio 14
VisualStudioVersion = 14.0.25420.1
# Visual Studio 15
VisualStudioVersion = 15.0.28307.960
MinimumVisualStudioVersion = 10.0.40219.1
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "SboxSvc", "core\svc\SboxSvc.vcxproj", "{2D3DBCAE-883E-54A6-F8F6-11228D989033}"
ProjectSection(ProjectDependencies) = postProject
@ -69,7 +69,7 @@ Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "SbieControl", "apps\control
{8E0EAA5B-6F5B-E0E2-338A-453EF2B548E4} = {8E0EAA5B-6F5B-E0E2-338A-453EF2B548E4}
EndProjectSection
EndProject
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "KmdUtil", "install\kmdutil\KmdUtil.vcxproj", "{0BF4988E-2325-4426-8CDC-BD221E4FB68C}"
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "kmdutil", "install\kmdutil\KmdUtil.vcxproj", "{0BF4988E-2325-4426-8CDC-BD221E4FB68C}"
ProjectSection(ProjectDependencies) = postProject
{8E0EAA5B-6F5B-E0E2-338A-453EF2B548E4} = {8E0EAA5B-6F5B-E0E2-338A-453EF2B548E4}
EndProjectSection
@ -88,6 +88,17 @@ Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "SboxHostDll", "SboxHostDll\
{8E0EAA5B-6F5B-E0E2-338A-453EF2B548E4} = {8E0EAA5B-6F5B-E0E2-338A-453EF2B548E4}
EndProjectSection
EndProject
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Docs", "Docs", "{666D2193-3CF6-4358-8312-67A0C2B09E35}"
ProjectSection(SolutionItems) = preProject
..\CHANGELOG.md = ..\CHANGELOG.md
EndProjectSection
EndProject
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "com", "com", "{7495BFF6-A576-4B96-9071-10CF956368FC}"
EndProject
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "core", "core", "{E9D1318A-FAF0-4EF8-8561-FCB03862AC99}"
EndProject
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "apps", "apps", "{0301861F-98D8-4767-BA7D-E146DE2E0C92}"
EndProject
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution
SbieDebug|Win32 = SbieDebug|Win32
@ -240,4 +251,23 @@ Global
GlobalSection(SolutionProperties) = preSolution
HideSolutionNode = FALSE
EndGlobalSection
GlobalSection(NestedProjects) = preSolution
{2D3DBCAE-883E-54A6-F8F6-11228D989033} = {E9D1318A-FAF0-4EF8-8561-FCB03862AC99}
{8B9E1B9D-FB3C-3009-9196-4315871BCD73} = {0301861F-98D8-4767-BA7D-E146DE2E0C92}
{E40CC819-6990-DA28-3E1F-6708BC98E37B} = {7495BFF6-A576-4B96-9071-10CF956368FC}
{8E0EAA5B-6F5B-E0E2-338A-453EF2B548E4} = {E9D1318A-FAF0-4EF8-8561-FCB03862AC99}
{41453A79-CA9B-ABCA-981C-5242AFC72DDF} = {7495BFF6-A576-4B96-9071-10CF956368FC}
{5410C534-4858-C748-86AD-0567A2451FDE} = {7495BFF6-A576-4B96-9071-10CF956368FC}
{8055A629-631E-84F5-8F3C-1908F264C81D} = {7495BFF6-A576-4B96-9071-10CF956368FC}
{42DB5510-0268-4655-B483-B9D6E4E48D62} = {7495BFF6-A576-4B96-9071-10CF956368FC}
{255002EC-9FC7-422E-B497-BE2CC5012B2D} = {E9D1318A-FAF0-4EF8-8561-FCB03862AC99}
{4019C5EB-8D1E-40E4-B7D1-5601B4B27288} = {E9D1318A-FAF0-4EF8-8561-FCB03862AC99}
{D16E291A-1F8A-4B19-AE07-0AF8CB7CCBD0} = {0301861F-98D8-4767-BA7D-E146DE2E0C92}
{0BF4988E-2325-4426-8CDC-BD221E4FB68C} = {0301861F-98D8-4767-BA7D-E146DE2E0C92}
{B8D7002B-0468-44E7-93A7-94327A5D7C7A} = {0301861F-98D8-4767-BA7D-E146DE2E0C92}
{3A42A9F3-E0C7-4633-9570-381802D6647D} = {E9D1318A-FAF0-4EF8-8561-FCB03862AC99}
EndGlobalSection
GlobalSection(ExtensibilityGlobals) = postSolution
SolutionGuid = {8CC68B2E-A32E-409D-8D3F-F68AF524E29C}
EndGlobalSection
EndGlobal

View File

@ -1,7 +1,7 @@

Microsoft Visual Studio Solution File, Format Version 12.00
# Visual Studio 14
VisualStudioVersion = 14.0.25420.1
# Visual Studio 15
VisualStudioVersion = 15.0.28307.1022
MinimumVisualStudioVersion = 10.0.40219.1
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "SboxDrv", "core\drv\SboxDrv.vcxproj", "{4019C5EB-8D1E-40E4-B7D1-5601B4B27288}"
ProjectSection(ProjectDependencies) = postProject
@ -27,6 +27,14 @@ Global
SbieRelease|x64 = SbieRelease|x64
EndGlobalSection
GlobalSection(ProjectConfigurationPlatforms) = postSolution
{4019C5EB-8D1E-40E4-B7D1-5601B4B27288}.Debug|Win32.ActiveCfg = SbieDebug|Win32
{4019C5EB-8D1E-40E4-B7D1-5601B4B27288}.Debug|Win32.Build.0 = SbieDebug|Win32
{4019C5EB-8D1E-40E4-B7D1-5601B4B27288}.Debug|x64.ActiveCfg = SbieDebug|x64
{4019C5EB-8D1E-40E4-B7D1-5601B4B27288}.Debug|x64.Build.0 = SbieDebug|x64
{4019C5EB-8D1E-40E4-B7D1-5601B4B27288}.Release|Win32.ActiveCfg = SbieRelease|Win32
{4019C5EB-8D1E-40E4-B7D1-5601B4B27288}.Release|Win32.Build.0 = SbieRelease|Win32
{4019C5EB-8D1E-40E4-B7D1-5601B4B27288}.Release|x64.ActiveCfg = SbieRelease|x64
{4019C5EB-8D1E-40E4-B7D1-5601B4B27288}.Release|x64.Build.0 = SbieRelease|x64
{4019C5EB-8D1E-40E4-B7D1-5601B4B27288}.SbieDebug|Win32.ActiveCfg = SbieDebug|Win32
{4019C5EB-8D1E-40E4-B7D1-5601B4B27288}.SbieDebug|Win32.Build.0 = SbieDebug|Win32
{4019C5EB-8D1E-40E4-B7D1-5601B4B27288}.SbieDebug|x64.ActiveCfg = SbieDebug|x64
@ -35,6 +43,14 @@ Global
{4019C5EB-8D1E-40E4-B7D1-5601B4B27288}.SbieRelease|Win32.Build.0 = SbieRelease|Win32
{4019C5EB-8D1E-40E4-B7D1-5601B4B27288}.SbieRelease|x64.ActiveCfg = SbieRelease|x64
{4019C5EB-8D1E-40E4-B7D1-5601B4B27288}.SbieRelease|x64.Build.0 = SbieRelease|x64
{63B0DDD2-5E3B-EF38-F711-9652D2EB73B3}.Debug|Win32.ActiveCfg = SbieRelease|Win32
{63B0DDD2-5E3B-EF38-F711-9652D2EB73B3}.Debug|Win32.Build.0 = SbieRelease|Win32
{63B0DDD2-5E3B-EF38-F711-9652D2EB73B3}.Debug|x64.ActiveCfg = SbieRelease|x64
{63B0DDD2-5E3B-EF38-F711-9652D2EB73B3}.Debug|x64.Build.0 = SbieRelease|x64
{63B0DDD2-5E3B-EF38-F711-9652D2EB73B3}.Release|Win32.ActiveCfg = SbieRelease|Win32
{63B0DDD2-5E3B-EF38-F711-9652D2EB73B3}.Release|Win32.Build.0 = SbieRelease|Win32
{63B0DDD2-5E3B-EF38-F711-9652D2EB73B3}.Release|x64.ActiveCfg = SbieRelease|x64
{63B0DDD2-5E3B-EF38-F711-9652D2EB73B3}.Release|x64.Build.0 = SbieRelease|x64
{63B0DDD2-5E3B-EF38-F711-9652D2EB73B3}.SbieDebug|Win32.ActiveCfg = SbieRelease|Win32
{63B0DDD2-5E3B-EF38-F711-9652D2EB73B3}.SbieDebug|Win32.Build.0 = SbieRelease|Win32
{63B0DDD2-5E3B-EF38-F711-9652D2EB73B3}.SbieDebug|x64.ActiveCfg = SbieRelease|x64
@ -43,6 +59,14 @@ Global
{63B0DDD2-5E3B-EF38-F711-9652D2EB73B3}.SbieRelease|Win32.Build.0 = SbieRelease|Win32
{63B0DDD2-5E3B-EF38-F711-9652D2EB73B3}.SbieRelease|x64.ActiveCfg = SbieRelease|x64
{63B0DDD2-5E3B-EF38-F711-9652D2EB73B3}.SbieRelease|x64.Build.0 = SbieRelease|x64
{7BA01954-12F1-4CEE-BA97-FAD3250D9776}.Debug|Win32.ActiveCfg = SbieRelease|Win32
{7BA01954-12F1-4CEE-BA97-FAD3250D9776}.Debug|Win32.Build.0 = SbieRelease|Win32
{7BA01954-12F1-4CEE-BA97-FAD3250D9776}.Debug|x64.ActiveCfg = SbieRelease|Win32
{7BA01954-12F1-4CEE-BA97-FAD3250D9776}.Debug|x64.Build.0 = SbieRelease|Win32
{7BA01954-12F1-4CEE-BA97-FAD3250D9776}.Release|Win32.ActiveCfg = SbieRelease|Win32
{7BA01954-12F1-4CEE-BA97-FAD3250D9776}.Release|Win32.Build.0 = SbieRelease|Win32
{7BA01954-12F1-4CEE-BA97-FAD3250D9776}.Release|x64.ActiveCfg = SbieRelease|Win32
{7BA01954-12F1-4CEE-BA97-FAD3250D9776}.Release|x64.Build.0 = SbieRelease|Win32
{7BA01954-12F1-4CEE-BA97-FAD3250D9776}.SbieDebug|Win32.ActiveCfg = SbieRelease|Win32
{7BA01954-12F1-4CEE-BA97-FAD3250D9776}.SbieDebug|Win32.Build.0 = SbieRelease|Win32
{7BA01954-12F1-4CEE-BA97-FAD3250D9776}.SbieDebug|x64.ActiveCfg = SbieRelease|Win32
@ -55,4 +79,7 @@ Global
GlobalSection(SolutionProperties) = preSolution
HideSolutionNode = FALSE
EndGlobalSection
GlobalSection(ExtensibilityGlobals) = postSolution
SolutionGuid = {806E7BFC-90B6-4D60-A232-3321EA1A60BA}
EndGlobalSection
EndGlobal

View File

@ -94,6 +94,8 @@ CMessageDialog::CMessageDialog(CWnd *pParentWnd, int mode)
m_buf_len = (8 * 1024);
m_buf = malloc_WCHAR(m_buf_len);
m_last_message_number = 0;
if (mode == MSGDLG_NORMAL)
ReloadConf();
@ -250,19 +252,23 @@ void CMessageDialog::OnTimer()
while (1) {
ULONG len = m_buf_len;
LONG status = SbieApi_GetWork(CMyApp::m_session_id, m_buf, &len);
if (status != 0)
break;
ULONG message_number = m_last_message_number;
ULONG code = -1;
LONG status = SbieApi_GetMessage(&message_number, CMyApp::m_session_id, &code, m_buf, len);
if (status != 0)
break; // error or no more entries
ULONG *type = (ULONG *)m_buf;
if (*type != API_LOG_MESSAGE)
//if (message_number != m_last_message_number + 1)
// we missed something
m_last_message_number = message_number;
if (code == 0)
continue; // empty dummy
if (/*code == MSG_2199 &&*/ m_firsttime)
continue;
ULONG code = type[1];
if (code == MSG_2199 && m_firsttime)
continue;
WCHAR *str1 = (WCHAR *)&type[2];
WCHAR *str1 = m_buf;
ULONG str1_len = wcslen(str1);
WCHAR *str2 = str1 + str1_len + 1;
ULONG str2_len = wcslen(str2);

View File

@ -55,6 +55,8 @@ class CMessageDialog : public CBaseDialog
CPtrArray m_hidden;
ULONG m_last_message_number;
BOOL IsHiddenMessage(
ULONG code, const WCHAR *detail_1, const WCHAR *detail_2);

View File

@ -41,6 +41,8 @@ CMonitorDialog::CMonitorDialog(CWnd *pParentWnd)
m_username[0] = L'\0';
m_username[255] = L'\0';
m_username_len = wcslen(m_username);
m_last_entry_seq_num = 0;
}
@ -105,15 +107,22 @@ void CMonitorDialog::OnIdle()
static const WCHAR *_Separator = L" -------------------------------";
CListBox *listbox = (CListBox *)GetDlgItem(ID_MESSAGE_LIST);
WCHAR name[280];
WCHAR name[300];
while (1) {
ULONG seq_num = m_last_entry_seq_num;
USHORT type;
SbieApi_MonitorGet(&type, &name[12]);
ULONG64 pid;
SbieApi_MonitorGetEx(&seq_num, &type, &pid, &name[12]);
if ((! type) || (! name[12]))
break;
if(seq_num != m_last_entry_seq_num + 1)
SbieApi_Log(MSG_1242, L"Resource access logger overflow!"); // MSG_MONITOR_OVERFLOW
m_last_entry_seq_num = seq_num;
// privacy protection, hide username
while (m_username_len) {
WCHAR *username_ptr = wcsstr(&name[12], m_username);
if (! username_ptr)
@ -126,12 +135,11 @@ void CMonitorDialog::OnIdle()
name[10] = L' ';
name[9] = L' ';
if (type & MONITOR_OPEN) {
type &= ~MONITOR_OPEN;
name[9] = L'O';
} else if (type & MONITOR_DENY) {
type &= ~MONITOR_DENY;
name[9] = L'X';
}
type &= 0x0FFF;
const WCHAR *PrefixPtr = _Unknown;
if (type == MONITOR_PIPE)
@ -152,6 +160,8 @@ void CMonitorDialog::OnIdle()
PrefixPtr = _Other;
wcsncpy(name, PrefixPtr, 9);
wsprintf(&name[wcslen(name)], L"; PID: %I64u", pid);
int index = listbox->AddString(name);
WCHAR oldname[280];

View File

@ -30,6 +30,7 @@ class CMonitorDialog : public CBaseDialog
WCHAR m_username[256];
ULONG m_username_len;
ULONG m_last_entry_seq_num;
virtual BOOL OnInitDialog();

View File

@ -22,7 +22,7 @@
#define MY_VERSION_BINARY 5,40
#define MY_VERSION_STRING "5.40"
#define MY_VERSION_STRING_EX "5.40.1"
#define MY_VERSION_STRING_EX "5.40.2"
// These #defines are used by either Resource Compiler, or by NSIC installer
#define SBIE_INSTALLER_PATH "..\\Bin\\"

View File

@ -218,7 +218,7 @@ typedef struct _OBJECT_BASIC_INFORMATION {
} OBJECT_BASIC_INFORMATION, *POBJECT_BASIC_INFORMATION;
typedef struct _OBJECT_NAME_INFORMATION {
UNICODE_STRING ObjectName;
UNICODE_STRING Name;
} OBJECT_NAME_INFORMATION, *POBJECT_NAME_INFORMATION;
typedef struct __PUBLIC_OBJECT_TYPE_INFORMATION {
@ -921,6 +921,24 @@ typedef enum _PROCESSINFOCLASS {
ProcessDebugObjectHandle, // 30
ProcessDebugFlags,
ProcessHandleTracing,
ProcessIoPriority,
ProcessExecuteFlags,
ProcessResourceManagement, // ProcessTlsInformation
ProcessCookie,
ProcessImageInformation,
ProcessCycleTime,
ProcessPagePriority,
ProcessInstrumentationCallback, // 40
ProcessThreadStackAllocation,
ProcessWorkingSetWatchEx,
ProcessImageFileNameWin32,
ProcessImageFileMapping,
ProcessAffinityUpdateMode,
ProcessMemoryAllocationMode,
ProcessGroupInformation,
ProcessTokenVirtualizationEnabled,
ProcessConsoleHostProcess,
ProcessWindowInformation, // 50
MaxProcessInfoClass // MaxProcessInfoClass should always be the last enum
} PROCESSINFOCLASS;
@ -931,7 +949,7 @@ typedef struct _PROCESS_BASIC_INFORMATION {
LONG BasePriority; // was type KPRIORITY
ULONG_PTR UniqueProcessId;
ULONG_PTR InheritedFromUniqueProcessId;
} PROCESS_BASIC_INFORMATION;
} PROCESS_BASIC_INFORMATION, *PPROCESS_BASIC_INFORMATION;
typedef struct _PROCESS_IMAGE_FILE_NAME {
USHORT Length;
@ -1241,56 +1259,110 @@ typedef enum _SYSTEM_INFORMATION_CLASS {
SystemProcessorInformation,
SystemPerformanceInformation,
SystemTimeOfDayInformation,
SystemNotImplemented1,
SystemPathInformation,
SystemProcessInformation, // 5
SystemCallCounts,
SystemConfigurationInformation,
SystemProcessorTimes,
SystemGlobalFlag,
SystemNotImplemented2, // 10
SystemCallCountInformation,
SystemDeviceInformation,
SystemProcessorPerformanceInformation,
SystemFlagsInformation,
SystemCallTimeInformation, // 10
SystemModuleInformation, // 11
SystemLockInformation,
SystemNotImplemented3,
SystemNotImplemented4,
SystemNotImplemented5,
SystemLocksInformation,
SystemStackTraceInformation,
SystemPagedPoolInformation,
SystemNonPagedPoolInformation,
SystemHandleInformation,
SystemObjectInformation,
SystemPagefileInformation,
SystemInstructionEmulationCounts,
SystemInvalidInfoClass1,
SystemCacheInformation,
SystemPoolTagInformation,
SystemProcessorStatistics,
SystemDpcInformation,
SystemNotImplemented6,
SystemLoadImage,
SystemUnloadImage,
SystemTimeAdjustment,
SystemNotImplemented7,
SystemNotImplemented8,
SystemNotImplemented9,
SystemPageFileInformation,
SystemVdmInstemulInformation,
SystemVdmBopInformation,
SystemFileCacheInformation,
SystemPoolTagInformation,
SystemInterruptInformation,
SystemDpcBehaviorInformation,
SystemFullMemoryInformation,
SystemLoadGdiDriverInformation,
SystemUnloadGdiDriverInformation,
SystemTimeAdjustmentInformation,
SystemSummaryMemoryInformation,
SystemMirrorMemoryInformation,
SystemPerformanceTraceInformation,
SystemCrashDumpInformation,
SystemExceptionInformation, // 33
SystemCrashDumpStateInformation,
SystemKernelDebuggerInformation,
SystemContextSwitchInformation,
SystemRegistryQuotaInformation, // 37
SystemLoadAndCallImage,
SystemPrioritySeparation,
SystemNotImplemented10,
SystemNotImplemented11,
SystemInvalidInfoClass2,
SystemInvalidInfoClass3,
SystemTimeZoneInformation,
SystemExtendServiceTableInformation,
SystemPrioritySeperation,
SystemVerifierAddDriverInformation,
SystemVerifierRemoveDriverInformation,
SystemProcessorIdleInformation,
SystemLegacyDriverInformation,
SystemCurrentTimeZoneInformation,
SystemLookasideInformation, // 45
SystemSetTimeSlipEvent,
SystemTimeSlipNotification,
SystemSessionCreate,
SystemSessionDetach,
SystemInvalidInfoClass4,
SystemSessionInformation,
SystemRangeStartInformation, // 50
SystemVerifierInformation,
SystemAddVerifier,
SystemSessionProcessesInformation
SystemVerifierThunkExtend,
SystemSessionProcessInformation,
SystemLoadGdiDriverInSystemSpace,
SystemNumaProcessorMap,
SystemPrefetcherInformation,
SystemExtendedProcessInformation,
SystemRecommendedSharedDataAlignment,
SystemComPlusPackage,
SystemNumaAvailableMemory,
SystemProcessorPowerInformation,
SystemEmulationBasicInformation, // WOW64
SystemEmulationProcessorInformation, // WOW64
SystemExtendedHandleInformation,
SystemLostDelayedWriteInformation,
SystemBigPoolInformation,
SystemSessionPoolTagInformation,
SystemSessionMappedViewInformation,
SystemHotpatchInformation,
SystemObjectSecurityMode,
SystemWatchdogTimerHandler,
SystemWatchdogTimerInformation,
SystemLogicalProcessorInformation,
SystemWow64SharedInformationObsolete,
SystemRegisterFirmwareTableInformationHandler,
SystemFirmwareTableInformation,
SystemModuleInformationEx,
SystemVerifierTriageInformation,
SystemSuperfetchInformation,
SystemMemoryListInformation,
SystemFileCacheInformationEx,
SystemThreadPriorityClientIdInformation,
SystemProcessorIdleCycleTimeInformation,
SystemVerifierCancellationInformation,
SystemProcessorPowerInformationEx,
SystemRefTraceInformation,
SystemSpecialPoolInformation,
SystemProcessIdInformation,
SystemErrorPortInformation,
SystemBootEnvironmentInformation,
SystemHypervisorInformation,
SystemVerifierInformationEx,
SystemTimeZoneInformation,
SystemImageFileExecutionOptionsInformation,
SystemCoverageInformation,
SystemPrefetchPatchInformation,
SystemVerifierFaultsInformation,
SystemSystemPartitionInformation,
SystemSystemDiskInformation,
SystemProcessorPerformanceDistribution,
SystemNumaProximityNodeInformation,
SystemDynamicTimeZoneInformation,
SystemCodeIntegrityInformation,
SystemProcessorMicrocodeUpdateInformation,
SystemProcessorBrandString,
SystemVirtualAddressInformation,
MaxSystemInfoClass
} SYSTEM_INFORMATION_CLASS;
typedef struct _MODULE_INFO {
@ -1711,10 +1783,11 @@ __declspec(dllimport) NTSTATUS NtUnloadDriver(
//---------------------------------------------------------------------------
typedef enum _MEMORY_INFORMATION_CLASS {
MemoryBasicInformation,
MemoryWorkingSetList,
MemorySectionName,
MemoryBasicVlmInformation
MemoryBasicInformation,
MemoryWorkingSetInformation,
MemoryMappedFilenameInformation,
MemoryRegionInformation,
MemoryWorkingSetExInformation
} MEMORY_INFORMATION_CLASS;
__declspec(dllimport) NTSTATUS NtAllocateVirtualMemory(

View File

@ -26,7 +26,8 @@ SbieApi_GetFileName=_SbieApi_GetFileName@12
SbieApi_GetHomePath=_SbieApi_GetHomePath@16
SbieApi_GetUnmountHive=_SbieApi_GetUnmountHive@4
SbieApi_GetVersion=_SbieApi_GetVersion@4
SbieApi_GetWork=_SbieApi_GetWork@12
;;; SbieApi_GetWork=_SbieApi_GetWork@12
SbieApi_GetMessage=_SbieApi_GetMessage@20
SbieApi_HookTramp=_SbieApi_HookTramp@8
@ -34,6 +35,7 @@ SbieApi_IsBoxEnabled=_SbieApi_IsBoxEnabled@4
SbieApi_MonitorControl=_SbieApi_MonitorControl@8
SbieApi_MonitorGet=_SbieApi_MonitorGet@8
SbieApi_MonitorGetEx=_SbieApi_MonitorGetEx@16
SbieApi_MonitorPut=_SbieApi_MonitorPut@8
SbieApi_MonitorPut2=_SbieApi_MonitorPut2@12

View File

@ -202,6 +202,7 @@ _FX int Debug_Init(void)
// break
//
OutputDebugString(L"Dll_ImageName: ");
OutputDebugString(Dll_ImageName);
//if (_wcsicmp(Dll_ImageName, L"explorer.exe") == 0) {
@ -223,7 +224,6 @@ _FX int Debug_Init(void)
if (0)
#endif
{
while (! IsDebuggerPresent()) {
OutputDebugString(L"BREAK\n");
Sleep(500);

View File

@ -28,6 +28,7 @@
#undef WITH_DEBUG
//#define WITH_DEBUG
//---------------------------------------------------------------------------
@ -35,7 +36,8 @@
#ifdef WITH_DEBUG
#define BREAK_IMAGE_1 L"java.exe" // L"jp2launcher.exe"
//#define BREAK_IMAGE_1 L"java.exe" // L"jp2launcher.exe"
#define BREAK_IMAGE_1 L"TestTarget.exe" // L"jp2launcher.exe"
int Debug_Init(void);

View File

@ -211,6 +211,10 @@ _FX void Dll_InitInjected(void)
ULONG BoxKeyPathLen;
ULONG BoxIpcPathLen;
#ifdef WITH_DEBUG
OutputDebugString(L"SbieDll: Dll_InitInjected");
#endif WITH_DEBUG
//
// confirm the process is sandboxed before going further
//
@ -690,7 +694,7 @@ _FX ULONG_PTR Dll_Ordinal1(
{
Ldr_Inject_Init(bHostInject);
}
//
// conclude the detour by passing control back to the original
// RtlFindActivationContextSectionString. the detour code used

View File

@ -461,7 +461,7 @@ _FX NTSTATUS File_GetName(
if (! NT_SUCCESS(status))
return status;
uni = &((OBJECT_NAME_INFORMATION *)name)->ObjectName;
uni = &((OBJECT_NAME_INFORMATION *)name)->Name;
#ifdef WOW64_FS_REDIR
//

View File

@ -1730,7 +1730,7 @@ _FX void File_GetSetDeviceMap(WCHAR *DeviceMap96)
} else {
UNICODE_STRING *uni =
&((OBJECT_NAME_INFORMATION *)dirname)->ObjectName;
&((OBJECT_NAME_INFORMATION *)dirname)->Name;
length = uni->Length / sizeof(WCHAR);
if (length > 95)
length = 95;

View File

@ -575,7 +575,7 @@ _FX NTSTATUS Ipc_GetName(
if (! NT_SUCCESS(status))
return status;
*OutTruePath = ((OBJECT_NAME_INFORMATION *)name)->ObjectName.Buffer;
*OutTruePath = ((OBJECT_NAME_INFORMATION *)name)->Name.Buffer;
if (! *OutTruePath) {
@ -588,7 +588,7 @@ _FX NTSTATUS Ipc_GetName(
}
name = (*OutTruePath)
+ ((OBJECT_NAME_INFORMATION *)name)->ObjectName.Length
+ ((OBJECT_NAME_INFORMATION *)name)->Name.Length
/ sizeof(WCHAR);
if (objname_len) {
@ -972,10 +972,10 @@ _FX void Ipc_AdjustPortPath(UNICODE_STRING *ObjectName)
status = Obj_GetObjectName(handle, name, &length);
if (NT_SUCCESS(status) &&
name->ObjectName.Length >= ParentLength * sizeof(WCHAR) &&
0 == _wcsnicmp(name->ObjectName.Buffer, Buffer, ParentLength)) {
name->Name.Length >= ParentLength * sizeof(WCHAR) &&
0 == _wcsnicmp(name->Name.Buffer, Buffer, ParentLength)) {
wmemcpy(Buffer, name->ObjectName.Buffer, ParentLength);
wmemcpy(Buffer, name->Name.Buffer, ParentLength);
}
Dll_Free(name);

View File

@ -399,7 +399,7 @@ _FX void Ldr_FixImagePath(void)
//
// if this is a forced program, we need to get the image path from
// the kernel (i.e. NtQueryVirtualMemory with MemorySectionName),
// the kernel (i.e. NtQueryVirtualMemory with MemoryMappedFilenameInformation),
// in case the image path contains symbolic links or reparse points.
// such links would have been translated by NtCreateFile if the
// program was started by another program in the sandbox. so if
@ -471,7 +471,7 @@ _FX WCHAR *Ldr_FixImagePath_2(void)
BufferLength = 256;
NameUni = Dll_AllocTemp((ULONG)BufferLength + sizeof(WCHAR) * 2);
status = __sys_NtQueryVirtualMemory(
NtCurrentProcess(), (void *)Ldr_ImageBase, MemorySectionName,
NtCurrentProcess(), (void *)Ldr_ImageBase, MemoryMappedFilenameInformation,
NameUni, BufferLength, &BufferLength);
if (status == STATUS_INFO_LENGTH_MISMATCH ||
@ -480,7 +480,7 @@ _FX WCHAR *Ldr_FixImagePath_2(void)
Dll_Free(NameUni);
NameUni = Dll_AllocTemp((ULONG)BufferLength + sizeof(WCHAR) * 2);
status = __sys_NtQueryVirtualMemory(
NtCurrentProcess(), (void *)Ldr_ImageBase, MemorySectionName,
NtCurrentProcess(), (void *)Ldr_ImageBase, MemoryMappedFilenameInformation,
NameUni, BufferLength, &BufferLength);
}

View File

@ -308,7 +308,7 @@ _FX NTSTATUS Obj_NtQueryVirtualMemory(
// if the request is not for an object name, then call the system
//
if (MemoryInformationClass != MemorySectionName) {
if (MemoryInformationClass != MemoryMappedFilenameInformation) {
return __sys_NtQueryVirtualMemory(
ProcessHandle, BaseAddress, MemoryInformationClass,
@ -328,7 +328,7 @@ _FX NTSTATUS Obj_NtQueryVirtualMemory(
}
status = __sys_NtQueryVirtualMemory(
ProcessHandle, BaseAddress, MemorySectionName,
ProcessHandle, BaseAddress, MemoryMappedFilenameInformation,
name, maxlen, &outlen);
if (status == STATUS_INFO_LENGTH_MISMATCH ||
@ -340,7 +340,7 @@ _FX NTSTATUS Obj_NtQueryVirtualMemory(
name = Dll_AllocTemp((ULONG)maxlen);
status = __sys_NtQueryVirtualMemory(
ProcessHandle, BaseAddress, MemorySectionName,
ProcessHandle, BaseAddress, MemoryMappedFilenameInformation,
name, maxlen, &outlen);
}

View File

@ -252,7 +252,7 @@ _FX LONG SbieApi_GetVersion(
// SbieApi_GetWork
//---------------------------------------------------------------------------
/*
_FX LONG SbieApi_GetWork(
ULONG SessionId,
void *Buffer,
@ -273,6 +273,40 @@ _FX LONG SbieApi_GetWork(
return status;
}
*/
//---------------------------------------------------------------------------
// SbieApi_GetMessage
//---------------------------------------------------------------------------
_FX LONG SbieApi_GetMessage(
ULONG* MessageNum,
ULONG SessionId,
ULONG *MessageId,
wchar_t *Buffer,
ULONG Length)
{
NTSTATUS status;
__declspec(align(8)) UNICODE_STRING64 msgtext;
__declspec(align(8)) ULONG64 parms[API_NUM_ARGS];
API_GET_MESSAGE_ARGS *args = (API_GET_MESSAGE_ARGS *)parms;
msgtext.MaximumLength = (USHORT)Length;
msgtext.Buffer = (ULONG_PTR)Buffer;
msgtext.Length = 0;
memzero(parms, sizeof(parms));
args->func_code = API_GET_MESSAGE;
args->msg_num.val = MessageNum;
args->session_id.val = SessionId;
args->msgid.val = MessageId;
args->msgtext.val = &msgtext;
status = SbieApi_Ioctl(parms);
return status;
}
//---------------------------------------------------------------------------
@ -1411,6 +1445,40 @@ _FX LONG SbieApi_MonitorGet(
}
//---------------------------------------------------------------------------
// SbieApi_MonitorGetEx
//---------------------------------------------------------------------------
_FX LONG SbieApi_MonitorGetEx(
ULONG *SeqNum,
USHORT *Type,
ULONG64 *Pid,
WCHAR *Name) // WCHAR [256]
{
NTSTATUS status;
__declspec(align(8)) ULONG64 parms[API_NUM_ARGS];
API_MONITOR_GET_EX_ARGS *args = (API_MONITOR_GET_EX_ARGS *)parms;
args->func_code = API_MONITOR_GET_EX;
args->name_seq.val64 = (ULONG64)(ULONG_PTR)SeqNum;
args->name_type.val64 = (ULONG64)(ULONG_PTR)Type;
args->name_pid.val64 = (ULONG64)(ULONG_PTR)Pid;
args->name_len.val64 = 256 * sizeof(WCHAR);
args->name_ptr.val64 = (ULONG64)(ULONG_PTR)Name;
status = SbieApi_Ioctl(parms);
if (!NT_SUCCESS(status)) {
if (Type)
*Type = 0;
if (Name)
*Name = L'\0';
}
return status;
}
//---------------------------------------------------------------------------
// SbieApi_GetUnmountHive
//---------------------------------------------------------------------------

View File

@ -62,11 +62,19 @@ SBIEAPI_EXPORT
SBIEAPI_EXPORT LONG SbieApi_GetVersion(
WCHAR *version_string); // WCHAR [16]
SBIEAPI_EXPORT
/*SBIEAPI_EXPORT
LONG SbieApi_GetWork(
ULONG SessionId,
void *Buffer,
ULONG *Length);
ULONG *Length);*/
SBIEAPI_EXPORT
LONG SbieApi_GetMessage(
ULONG* MessageNum,
ULONG SessionId,
ULONG *MessageId,
wchar_t *Buffer,
ULONG Length);
SBIEAPI_EXPORT LONG SbieApi_Log(
ULONG msgid, const WCHAR *format, ...);
@ -196,6 +204,13 @@ LONG SbieApi_MonitorGet(
USHORT *Type,
WCHAR *Name); // WCHAR [256]
SBIEAPI_EXPORT
LONG SbieApi_MonitorGetEx(
ULONG *SeqNum,
USHORT *Type,
ULONG64 *Pid,
WCHAR *Name); // WCHAR [256]
//---------------------------------------------------------------------------
@ -288,8 +303,6 @@ LONG SbieApi_QuerySymbolicLink(
SBIEAPI_EXPORT
LONG SbieApi_ReloadConf(ULONG session_id);
SBIEAPI_EXPORT
LONG SbieApi_ReloadConf2(ULONG session_id, const WCHAR *config_path);
SBIEAPI_EXPORT
LONG SbieApi_QueryConf(

View File

@ -825,7 +825,7 @@ _FX BOOL SbieDll_StartBoxedService(const WCHAR *ServiceName, BOOLEAN WithAdd)
ULONG retries, error;
//WCHAR text[130];
//Sbie_swprintf(text, L"StartBoxedService; name: '%s'; pid: %d", ServiceName, GetCurrentProcessId()); // fix-me: pottential buffer overflow
//Sbie_swprintf(text, L"StartBoxedService; name: '%s'", ServiceName); // fix-me: pottential buffer overflow
//SbieApi_MonitorPut(MONITOR_OTHER, text);
//
@ -1096,7 +1096,7 @@ _FX BOOL Scm_StartServiceW(
return FALSE;
WCHAR text[130];
Sbie_swprintf(text, L"StartService; name: '%s'; pid: %d", ServiceName, GetCurrentProcessId()); // fix-me: pottential buffer overflow
Sbie_swprintf(text, L"StartService: %s", ServiceName); // fix-me: pottential buffer overflow
SbieApi_MonitorPut(MONITOR_OTHER, text);
if (Scm_IsBoxedService(ServiceName))
@ -1263,7 +1263,7 @@ _FX BOOL Scm_StartServiceCtrlDispatcherX(
}
//WCHAR text[130];
//Sbie_swprintf(text, L"StartServiceCtrlDispatcher; name: '%s'; pid %d", ServiceName, GetCurrentProcessId()); // fix-me: pottential buffer overflow
//Sbie_swprintf(text, L"StartServiceCtrlDispatcher; name: '%s'", ServiceName); // fix-me: pottential buffer overflow
//SbieApi_MonitorPut(MONITOR_OTHER, text);
//

View File

@ -668,7 +668,7 @@ _FX NTSTATUS Secure_NtSetSecurityObject(
OBJECT_NAME_INFORMATION *name =
(OBJECT_NAME_INFORMATION *)name_space;
status = Obj_GetObjectName(Handle, name, &name_len);
if (NT_SUCCESS(status) && name->ObjectName.Length == 0) {
if (NT_SUCCESS(status) && name->Name.Length == 0) {
IsUnnamedObject = TRUE;
}

View File

@ -636,6 +636,7 @@ static UCHAR Support_BuiltinDomainRid[12] = {
#endif /* SBIEDLL_FORMATMESSAGE_ONLY */
#if 1
//---------------------------------------------------------------------------
// SbieDll_FormatMessage_2
@ -844,3 +845,5 @@ _FX WCHAR *SbieDll_FormatMessage2(
ins[2] = ins2;
return SbieDll_FormatMessage(code, ins);
}
#endif

View File

@ -304,6 +304,7 @@
<ClCompile Include="process_hook.c" />
<ClCompile Include="process_low.c" />
<ClCompile Include="process_util.c" />
<ClCompile Include="log_buff.c" />
<ClCompile Include="session.c" />
<ClCompile Include="syscall.c" />
<ClCompile Include="syscall_32.c">
@ -384,6 +385,7 @@
<ClInclude Include="my_winnt.h" />
<ClInclude Include="obj.h" />
<ClInclude Include="process.h" />
<ClInclude Include="log_buff.h" />
<ClInclude Include="session.h" />
<ClInclude Include="syscall.h" />
<ClInclude Include="thread.h" />

View File

@ -25,6 +25,7 @@
#include "util.h"
#include "hook.h"
#include "common/my_version.h"
#include "log_buff.h"
//---------------------------------------------------------------------------
@ -49,7 +50,7 @@ static BOOLEAN Api_FastIo_DEVICE_CONTROL(
ULONG IoControlCode, IO_STATUS_BLOCK *IoStatus,
DEVICE_OBJECT *DeviceObject);
static void Api_DelWork(API_WORK_ITEM *work_item);
//static void Api_DelWork(API_WORK_ITEM *work_item);
//---------------------------------------------------------------------------
@ -59,6 +60,8 @@ static NTSTATUS Api_GetVersion(PROCESS *proc, ULONG64 *parms);
static NTSTATUS Api_LogMessage(PROCESS *proc, ULONG64 *parms);
static NTSTATUS Api_GetMessage(PROCESS *proc, ULONG64 *parms);
static NTSTATUS Api_GetWork(PROCESS *proc, ULONG64 *parms);
static NTSTATUS Api_GetHomePath(PROCESS *proc, ULONG64 *parms);
@ -92,9 +95,11 @@ volatile HANDLE Api_ServiceProcessId = NULL;
static PERESOURCE Api_LockResource = NULL;
static LIST Api_WorkList;
//static LIST Api_WorkList;
static BOOLEAN Api_WorkListInitialized = FALSE;
static LOG_BUFFER* Api_LogBuffer = NULL;
static volatile LONG Api_UseCount = -1;
@ -108,11 +113,17 @@ _FX BOOLEAN Api_Init(void)
NTSTATUS status;
UNICODE_STRING uni;
//
// initialize log buffer
//
Api_LogBuffer = log_buffer_init(8 * 8 * 1024);
//
// initialize work list
//
List_Init(&Api_WorkList);
//List_Init(&Api_WorkList);
if (! Mem_GetLockResource(&Api_LockResource, TRUE))
return FALSE;
@ -168,6 +179,7 @@ _FX BOOLEAN Api_Init(void)
Api_SetFunction(API_GET_VERSION, Api_GetVersion);
Api_SetFunction(API_GET_WORK, Api_GetWork);
Api_SetFunction(API_LOG_MESSAGE, Api_LogMessage);
Api_SetFunction(API_GET_MESSAGE, Api_GetMessage);
Api_SetFunction(API_GET_HOME_PATH, Api_GetHomePath);
Api_SetFunction(API_SET_SERVICE_PORT, Api_SetServicePort);
@ -195,8 +207,6 @@ _FX BOOLEAN Api_Init(void)
_FX void Api_Unload(void)
{
API_WORK_ITEM *work_item;
if (Api_DeviceObject) {
IoDeleteDevice(Api_DeviceObject);
Api_DeviceObject = NULL;
@ -209,12 +219,18 @@ _FX void Api_Unload(void)
if (Api_WorkListInitialized) {
while (1) {
if (Api_LogBuffer) {
log_buffer_free(Api_LogBuffer);
Api_LogBuffer = NULL;
}
/*API_WORK_ITEM *work_item;
while (1) {
work_item = List_Head(&Api_WorkList);
if (! work_item)
break;
Api_DelWork(work_item);
}
}*/
Mem_FreeLockResource(&Api_LockResource);
@ -612,6 +628,136 @@ _FX NTSTATUS Api_LogMessage(PROCESS *proc, ULONG64 *parms)
}
//---------------------------------------------------------------------------
// Api_AddMessage
//---------------------------------------------------------------------------
_FX void Api_AddMessage(
NTSTATUS error_code,
const WCHAR *string1, ULONG string1_len,
const WCHAR *string2, ULONG string2_len,
ULONG session_id)
{
KIRQL irql;
if (!Api_WorkListInitialized) // if (!Api_LogBuffer)
return;
//
// add work at the end of the work list
//
irql = Api_EnterCriticalSection();
ULONG entry_size = sizeof(ULONG) // session_id
+ sizeof(ULONG) // error_code
+ (string1_len + 1) * sizeof(WCHAR)
+ (string2_len + 1) * sizeof(WCHAR);
CHAR* write_ptr = log_buffer_push_entry((LOG_BUFFER_SIZE_T)entry_size, Api_LogBuffer);
if (write_ptr) {
//[session_id 4][error_code 4][string1 n*2][\0 2][string2 n*2][\0 2]
WCHAR null_char = L'\0';
log_buffer_push_bytes((CHAR*)&session_id, sizeof(ULONG), &write_ptr, Api_LogBuffer);
log_buffer_push_bytes((CHAR*)&error_code, sizeof(ULONG), &write_ptr, Api_LogBuffer);
log_buffer_push_bytes((CHAR*)string1, string1_len * sizeof(WCHAR), &write_ptr, Api_LogBuffer);
log_buffer_push_bytes((CHAR*)&null_char, sizeof(WCHAR), &write_ptr, Api_LogBuffer);
log_buffer_push_bytes((CHAR*)string2, string2_len * sizeof(WCHAR), &write_ptr, Api_LogBuffer);
log_buffer_push_bytes((CHAR*)&null_char, sizeof(WCHAR), &write_ptr, Api_LogBuffer);
}
// else // this can only happen when the entire buffer is to small to hold this entire entry
// if loging fails we can't log this error :/
Api_LeaveCriticalSection(irql);
}
//---------------------------------------------------------------------------
// Api_GetMessage
//---------------------------------------------------------------------------
_FX NTSTATUS Api_GetMessage(PROCESS *proc, ULONG64 *parms)
{
API_GET_MESSAGE_ARGS *args = (API_GET_MESSAGE_ARGS *)parms;
NTSTATUS status = STATUS_SUCCESS;
UNICODE_STRING64 *msgtext;
WCHAR *msgtext_buffer;
KIRQL irql;
if (proc)
return STATUS_NOT_IMPLEMENTED;
ProbeForRead(args->msg_num.val, sizeof(ULONG), sizeof(ULONG));
ProbeForWrite(args->msg_num.val, sizeof(ULONG), sizeof(ULONG));
ProbeForWrite(args->msgid.val, sizeof(ULONG), sizeof(ULONG));
msgtext = args->msgtext.val;
if (!msgtext)
return STATUS_INVALID_PARAMETER;
ProbeForRead(msgtext, sizeof(UNICODE_STRING64), sizeof(ULONG));
ProbeForWrite(msgtext, sizeof(UNICODE_STRING64), sizeof(ULONG));
msgtext_buffer = (WCHAR *)msgtext->Buffer;
if (!msgtext_buffer)
return STATUS_INVALID_PARAMETER;
irql = Api_EnterCriticalSection();
__try {
CHAR* read_ptr = log_buffer_get_next(*args->msg_num.val, Api_LogBuffer);
if (!read_ptr) {
status = STATUS_NO_MORE_ENTRIES;
} else {
LOG_BUFFER_SIZE_T entry_size = log_buffer_get_size(&read_ptr, Api_LogBuffer);
LOG_BUFFER_SEQ_T seq_number = log_buffer_get_seq_num(&read_ptr, Api_LogBuffer);
*args->msg_num.val = seq_number;
//[session_id 4][error_code 4][string1 n*2][\0 2][string2 n*2][\0 2]
ULONG session_id;
log_buffer_get_bytes((CHAR*)&session_id, 4, &read_ptr, Api_LogBuffer);
if (session_id == args->session_id.val) {
log_buffer_get_bytes((CHAR*)args->msgid.val, 4, &read_ptr, Api_LogBuffer);
SIZE_T msg_length = entry_size - (4 + 4);
if (msg_length <= msgtext->MaximumLength)
{
msgtext->Length = (USHORT)msg_length;
ProbeForWrite(msgtext_buffer, msg_length, sizeof(WCHAR));
memcpy(msgtext_buffer, read_ptr, msg_length);
}
else
{
status = STATUS_BUFFER_TOO_SMALL;
}
} else {
// this entry is not for us, so we return an empty result to maintain sequence consistency
*args->msgid.val = 0;
}
}
} __except (EXCEPTION_EXECUTE_HANDLER) {
status = GetExceptionCode();
}
Api_LeaveCriticalSection(irql);
return status;
}
//---------------------------------------------------------------------------
// Api_SendServiceMessage
//---------------------------------------------------------------------------
@ -709,7 +855,7 @@ _FX BOOLEAN Api_SendServiceMessage(ULONG msgid, ULONG data_len, void *data)
//---------------------------------------------------------------------------
_FX BOOLEAN Api_AddWork(API_WORK_ITEM *work_item)
/*_FX BOOLEAN Api_AddWork(API_WORK_ITEM *work_item)
{
KIRQL irql;
@ -734,7 +880,7 @@ _FX BOOLEAN Api_AddWork(API_WORK_ITEM *work_item)
return TRUE;
return TRUE;
}
}*/
//---------------------------------------------------------------------------
@ -742,13 +888,13 @@ _FX BOOLEAN Api_AddWork(API_WORK_ITEM *work_item)
//---------------------------------------------------------------------------
_FX void Api_DelWork(API_WORK_ITEM *work_item)
/*_FX void Api_DelWork(API_WORK_ITEM *work_item)
{
// this assumes Api_WorkList is already locked using Api_Lock
List_Remove(&Api_WorkList, work_item);
Mem_Free(work_item, work_item->length);
}
}*/
//---------------------------------------------------------------------------
@ -758,7 +904,9 @@ _FX void Api_DelWork(API_WORK_ITEM *work_item)
_FX NTSTATUS Api_GetWork(PROCESS *proc, ULONG64 *parms)
{
API_GET_WORK_ARGS *args = (API_GET_WORK_ARGS *)parms;
return STATUS_NOT_IMPLEMENTED;
/*API_GET_WORK_ARGS *args = (API_GET_WORK_ARGS *)parms;
NTSTATUS status;
void *buffer_ptr;
ULONG buffer_len;
@ -834,7 +982,7 @@ _FX NTSTATUS Api_GetWork(PROCESS *proc, ULONG64 *parms)
Api_LeaveCriticalSection(irql);
return status;
return status;*/
}

View File

@ -38,7 +38,7 @@
//---------------------------------------------------------------------------
typedef struct _API_WORK_ITEM {
/*typedef struct _API_WORK_ITEM {
LIST_ELEM list_elem;
ULONG length; // length includes both header and data
@ -47,7 +47,7 @@ typedef struct _API_WORK_ITEM {
ULONG data[1];
} API_WORK_ITEM;
} API_WORK_ITEM;*/
typedef struct _Sbie_SeFilterTokenArg
{
@ -110,7 +110,19 @@ BOOLEAN Api_SendServiceMessage(ULONG msgid, ULONG data_len, void *data);
// allocate work_item from Driver_Pool, and initialize type, length and data
//
BOOLEAN Api_AddWork(API_WORK_ITEM *work_item);
//BOOLEAN Api_AddWork(API_WORK_ITEM *work_item);
//
// Add message to log buffer
//
void Api_AddMessage(
NTSTATUS error_code,
const WCHAR *string1, ULONG string1_len,
const WCHAR *string2, ULONG string2_len,
ULONG session_id);
//
// Copies boxname parameter from user

View File

@ -147,6 +147,8 @@ enum {
API_GET_WPAD_PORT,
API_SET_GAME_CONFIG_STORE_PORT,
API_SET_SMART_CARD_PORT,
API_MONITOR_GET_EX,
API_GET_MESSAGE,
API_LAST
};
@ -189,12 +191,12 @@ API_ARGS_FIELD(WCHAR *,string)
API_ARGS_CLOSE(API_GET_VERSION_ARGS)
API_ARGS_BEGIN(API_GET_WORK_ARGS)
/*API_ARGS_BEGIN(API_GET_WORK_ARGS)
API_ARGS_FIELD(ULONG,session_id)
API_ARGS_FIELD(void *,buffer)
API_ARGS_FIELD(ULONG,buffer_len)
API_ARGS_FIELD(ULONG *,result_len_ptr)
API_ARGS_CLOSE(API_GET_WORK_ARGS)
API_ARGS_CLOSE(API_GET_WORK_ARGS)*/
API_ARGS_BEGIN(API_LOG_MESSAGE_ARGS)
@ -203,6 +205,12 @@ API_ARGS_FIELD(ULONG,msgid)
API_ARGS_FIELD(UNICODE_STRING64 *,msgtext)
API_ARGS_CLOSE(API_LOG_MESSAGE_ARGS)
API_ARGS_BEGIN(API_GET_MESSAGE_ARGS)
API_ARGS_FIELD(ULONG *, msg_num)
API_ARGS_FIELD(ULONG, session_id)
API_ARGS_FIELD(ULONG *, msgid)
API_ARGS_FIELD(UNICODE_STRING64 *, msgtext)
API_ARGS_CLOSE(API_GET_MESSAGE_ARGS)
API_ARGS_BEGIN(API_QUERY_PROCESS_ARGS)
API_ARGS_FIELD(HANDLE,process_id)
@ -311,6 +319,14 @@ API_ARGS_FIELD(ULONG,name_len)
API_ARGS_FIELD(WCHAR *,name_ptr)
API_ARGS_CLOSE(API_MONITOR_GET_PUT_ARGS)
API_ARGS_BEGIN(API_MONITOR_GET_EX_ARGS)
API_ARGS_FIELD(ULONG *, name_seq)
API_ARGS_FIELD(USHORT *, name_type)
API_ARGS_FIELD(ULONG64 *, name_pid)
API_ARGS_FIELD(ULONG, name_len)
API_ARGS_FIELD(WCHAR *, name_ptr)
API_ARGS_CLOSE(API_MONITOR_GET_EX_ARGS)
API_ARGS_BEGIN(API_MONITOR_PUT2_ARGS)
API_ARGS_FIELD(USHORT *,name_type)
API_ARGS_FIELD(ULONG,name_len)

View File

@ -989,7 +989,7 @@ _FX NTSTATUS File_Generic_MyParseProc(
if (Session_MonitorCount &&
device_type != FILE_DEVICE_PHYSICAL_NETCARD)
Session_MonitorPut(MONITOR_IGNORE, ignore_str + 4);
Session_MonitorPut(MONITOR_IGNORE, ignore_str + 4, proc->pid);
Mem_Free(ignore_str, ignore_str_len);
}
@ -1504,12 +1504,11 @@ skip_due_to_home_folder:
mon_type |= MONITOR_OPEN;
else
mon_type |= MONITOR_DENY;
Session_MonitorPut(mon_type, mon_name);
Session_MonitorPut(mon_type, mon_name, proc->pid);
} else if (ShouldMonitorAccess) {
Session_MonitorPut(
MONITOR_FILE_OR_KEY | MONITOR_DENY, Name->Name.Buffer);
Session_MonitorPut(MONITOR_FILE_OR_KEY | MONITOR_DENY, Name->Name.Buffer, proc->pid);
} else if (msg1313 && status == STATUS_ACCESS_DENIED
&& device_type == FILE_DEVICE_DISK

View File

@ -1334,7 +1334,7 @@ _FX ULONG_PTR Gui_NtUserPostThreadMessage(
--nptr; *nptr = L':';
--nptr; *nptr = L'$';
Session_MonitorPut(mon_type, nptr);
Session_MonitorPut(mon_type, nptr, proc->pid);
Mem_Free(nbuf, nlen);
}

View File

@ -940,7 +940,7 @@ _FX NTSTATUS Ipc_CheckGenericObject(
mon_type |= MONITOR_OPEN;
else
mon_type |= MONITOR_DENY;
Session_MonitorPut(mon_type, mon_name);
Session_MonitorPut(mon_type, mon_name, proc->pid);
}
// DbgPrint("Process <%06d> Status <%08X> Object <%S>\n", proc->pid, status, Name->Name.Buffer);

View File

@ -470,8 +470,7 @@ _FX NTSTATUS Key_MyParseProc_2(OBJ_PARSE_PROC_ARGS_2)
if (ShouldMonitorAccess) {
Session_MonitorPut(
MONITOR_FILE_OR_KEY | MONITOR_DENY, Name->Name.Buffer);
Session_MonitorPut(MONITOR_FILE_OR_KEY | MONITOR_DENY, Name->Name.Buffer, proc->pid);
}
Mem_Free(Name, NameLength);

View File

@ -25,7 +25,6 @@
#include "api.h"
#include "util.h"
//---------------------------------------------------------------------------
// Functions
//---------------------------------------------------------------------------
@ -36,11 +35,11 @@ static void Log_Event_Msg(
const WCHAR *string1,
const WCHAR *string2);
static void Log_Popup_Msg_2(
/*static void Log_Popup_Msg_2(
NTSTATUS error_code,
const WCHAR *string1, ULONG string1_len,
const WCHAR *string2, ULONG string2_len,
ULONG session_id);
ULONG session_id);*/
//---------------------------------------------------------------------------
@ -133,14 +132,16 @@ _FX void Log_Popup_Msg(
if ((Driver_OsVersion >= DRIVER_WINDOWS_VISTA) && (session_id == 0))
session_id = 1;
Log_Popup_Msg_2(
//Log_Popup_Msg_2(
Api_AddMessage(
error_code, string1, string1_len, string2, string2_len, session_id);
//
// log message to SbieSvc and trigger SbieSvc to wake up and collect it
//
Log_Popup_Msg_2(
//Log_Popup_Msg_2(
Api_AddMessage(
error_code, string1, string1_len, string2, string2_len, -1);
string1_len = 0;
@ -155,7 +156,7 @@ _FX void Log_Popup_Msg(
//---------------------------------------------------------------------------
_FX void Log_Popup_Msg_2(
/*_FX void Log_Popup_Msg_2(
NTSTATUS error_code,
const WCHAR *string1, ULONG string1_len,
const WCHAR *string2, ULONG string2_len,
@ -202,7 +203,7 @@ _FX void Log_Popup_Msg_2(
Api_AddWork(work_item);
}
}
}*/
//---------------------------------------------------------------------------

View File

@ -26,6 +26,7 @@
#include "api.h"
#include "process.h"
#include "obj.h"
#include "log_buff.h"
//---------------------------------------------------------------------------
@ -70,9 +71,7 @@ struct _SESSION {
// resource monitor
//
WCHAR *monitor_buf;
WCHAR *monitor_read_ptr;
WCHAR *monitor_write_ptr;
LOG_BUFFER* monitor_log;
};
@ -110,6 +109,8 @@ static NTSTATUS Session_Api_MonitorPut2(PROCESS *proc, ULONG64 *parms);
static NTSTATUS Session_Api_MonitorGet(PROCESS *proc, ULONG64 *parms);
static NTSTATUS Session_Api_MonitorGetEx(PROCESS *proc, ULONG64 *parms);
//---------------------------------------------------------------------------
@ -150,6 +151,7 @@ _FX BOOLEAN Session_Init(void)
Api_SetFunction(API_MONITOR_PUT, Session_Api_MonitorPut);
Api_SetFunction(API_MONITOR_PUT2, Session_Api_MonitorPut2);
Api_SetFunction(API_MONITOR_GET, Session_Api_MonitorGet);
Api_SetFunction(API_MONITOR_GET_EX, Session_Api_MonitorGetEx);
//
// initialize set of recognized objects types for Session_Api_MonitorPut
@ -338,8 +340,8 @@ _FX void Session_Cancel(HANDLE ProcessId)
while (session) {
if ((session->leader_pid == ProcessId) || (! ProcessId)) {
if (session->monitor_buf) {
ExFreePoolWithTag(session->monitor_buf, tzuk);
if (session->monitor_log) {
log_buffer_free(session->monitor_log);
InterlockedDecrement(&Session_MonitorCount);
}
@ -573,7 +575,7 @@ _FX BOOLEAN Session_IsForceDisabled(ULONG SessionId)
//---------------------------------------------------------------------------
_FX void Session_MonitorPut(USHORT type, const WCHAR *name)
_FX void Session_MonitorPut(USHORT type, const WCHAR *name, HANDLE pid)
{
SESSION *session;
KIRQL irql;
@ -582,41 +584,22 @@ _FX void Session_MonitorPut(USHORT type, const WCHAR *name)
if (! session)
return;
if (session->monitor_buf && *name) {
if (session->monitor_log && *name) {
WCHAR *buf0 = session->monitor_buf;
WCHAR *wptr = session->monitor_write_ptr;
WCHAR *rptr = session->monitor_read_ptr;
ULONG64 pid64 = (ULONG64)pid;
SIZE_T data_len = (wcslen(name) + 1) * 2;
ULONG name_len = wcslen(name) + 1;
//[Type 2][PID 8][Data n*2]
SIZE_T entry_size = 2 + 8 + data_len;
BOOLEAN first = TRUE;
while (name_len) {
if (first) {
first = FALSE;
*wptr = type;
} else {
*wptr = *name;
++name;
--name_len;
}
++wptr;
if (wptr >= buf0 + SESSION_MONITOR_BUF_SIZE)
wptr = buf0;
if (wptr == rptr) {
Log_Msg0(MSG_MONITOR_OVERFLOW);
*buf0 = L'\0';
wptr = buf0;
session->monitor_read_ptr = buf0;
break;
}
}
*wptr = L'\0';
session->monitor_write_ptr = wptr;
CHAR* write_ptr = log_buffer_push_entry((LOG_BUFFER_SIZE_T)entry_size, session->monitor_log);
if (write_ptr) {
log_buffer_push_bytes((CHAR*)&type, 2, &write_ptr, session->monitor_log);
log_buffer_push_bytes((CHAR*)&pid64, 8, &write_ptr, session->monitor_log);
log_buffer_push_bytes((CHAR*)name, data_len, &write_ptr, session->monitor_log);
}
else // this can only happen when the entire buffer is to small to hold this entire entry
Log_Msg0(MSG_MONITOR_OVERFLOW);
}
Session_Unlock(irql);
@ -650,7 +633,7 @@ _FX NTSTATUS Session_Api_MonitorControl(PROCESS *proc, ULONG64 *parms)
*out_flag = FALSE;
session = Session_Get(FALSE, -1, &irql);
if (session) {
if (session->monitor_buf)
if (session->monitor_log)
*out_flag = TRUE;
Session_Unlock(irql);
}
@ -676,24 +659,18 @@ _FX NTSTATUS Session_Api_MonitorControl(PROCESS *proc, ULONG64 *parms)
session = Session_Get(FALSE, -1, &irql);
if (session) {
if (EnableMonitor && (! session->monitor_buf)) {
if (EnableMonitor && (! session->monitor_log)) {
session->monitor_buf = ExAllocatePoolWithTag(PagedPool,
SESSION_MONITOR_BUF_SIZE * sizeof(WCHAR), tzuk);
session->monitor_write_ptr = session->monitor_buf;
session->monitor_read_ptr = session->monitor_buf;
if (session->monitor_buf) {
*session->monitor_buf = L'\0';
session->monitor_log = log_buffer_init(SESSION_MONITOR_BUF_SIZE * sizeof(WCHAR));
if (session->monitor_log) {
InterlockedIncrement(&Session_MonitorCount);
} else
Log_Msg0(MSG_1201);
} else if ((! EnableMonitor) && session->monitor_buf) {
} else if ((! EnableMonitor) && session->monitor_log) {
ExFreePoolWithTag(session->monitor_buf, tzuk);
session->monitor_buf = NULL;
session->monitor_write_ptr = session->monitor_buf;
session->monitor_read_ptr = session->monitor_buf;
log_buffer_free(session->monitor_log);
session->monitor_log = NULL;
InterlockedDecrement(&Session_MonitorCount);
}
@ -895,7 +872,7 @@ _FX NTSTATUS Session_Api_MonitorPut2(PROCESS *proc, ULONG64 *parms)
name[1] = L'\0';
}
Session_MonitorPut(type, name);
Session_MonitorPut(type, name, proc->pid);
}
Mem_Free(name, 260 * sizeof(WCHAR));
@ -908,12 +885,25 @@ _FX NTSTATUS Session_Api_MonitorPut2(PROCESS *proc, ULONG64 *parms)
// Session_Api_MonitorGet
//---------------------------------------------------------------------------
_FX NTSTATUS Session_Api_MonitorGet(PROCESS *proc, ULONG64 *parms)
{
API_MONITOR_GET_PUT_ARGS *args = (API_MONITOR_GET_PUT_ARGS *)parms;
API_MONITOR_GET_PUT_ARGS *args = (API_MONITOR_GET_PUT_ARGS *)parms;
API_MONITOR_GET_EX_ARGS args2 = { args->func_code, 0, args->name_type.val64, 0, args->name_len.val64, args->name_ptr.val64 };
return Session_Api_MonitorGetEx(proc, (ULONG64*)&args2);
}
//---------------------------------------------------------------------------
// Session_Api_MonitorGet
//---------------------------------------------------------------------------
_FX NTSTATUS Session_Api_MonitorGetEx(PROCESS *proc, ULONG64 *parms)
{
API_MONITOR_GET_EX_ARGS *args = (API_MONITOR_GET_EX_ARGS *)parms;
NTSTATUS status;
ULONG *seq_num;
USHORT *user_type;
ULONG64 *user_pid;
ULONG name_len;
WCHAR *user_name;
SESSION *session;
@ -922,9 +912,19 @@ _FX NTSTATUS Session_Api_MonitorGet(PROCESS *proc, ULONG64 *parms)
if (proc)
return STATUS_NOT_IMPLEMENTED;
seq_num = args->name_seq.val;
if (seq_num != NULL) {
ProbeForRead(seq_num, sizeof(ULONG), sizeof(ULONG));
ProbeForWrite(seq_num, sizeof(ULONG), sizeof(ULONG));
}
user_type = args->name_type.val;
ProbeForWrite(user_type, sizeof(USHORT), sizeof(USHORT));
user_pid = args->name_pid.val;
if(user_pid != NULL)
ProbeForWrite(user_pid, sizeof(ULONG64), sizeof(ULONG64));
name_len = args->name_len.val / sizeof(WCHAR);
if ((! name_len) || name_len > 256)
return STATUS_INVALID_PARAMETER;
@ -932,6 +932,8 @@ _FX NTSTATUS Session_Api_MonitorGet(PROCESS *proc, ULONG64 *parms)
ProbeForWrite(user_name, name_len * sizeof(WCHAR), sizeof(WCHAR));
*user_type = 0;
if (user_pid != NULL)
*user_pid = 0;
*user_name = L'\0';
status = STATUS_SUCCESS;
@ -941,39 +943,31 @@ _FX NTSTATUS Session_Api_MonitorGet(PROCESS *proc, ULONG64 *parms)
__try {
if (session->monitor_buf) {
if (session->monitor_log) {
WCHAR *buf0 = session->monitor_buf;
WCHAR *rptr = session->monitor_read_ptr;
BOOLEAN first = TRUE;
CHAR* read_ptr = NULL;
if (seq_num != NULL)
read_ptr = log_buffer_get_next(*seq_num, session->monitor_log);
else if (session->monitor_log->buffer_size > 0) // for compatybility with older versions we return the oldest entry
read_ptr = session->monitor_log->buffer_start_ptr;
if (*rptr) {
if (read_ptr != NULL) {
LOG_BUFFER_SIZE_T entry_size = log_buffer_get_size(&read_ptr, session->monitor_log);
LOG_BUFFER_SEQ_T seq_number = log_buffer_get_seq_num(&read_ptr, session->monitor_log);
if (seq_num != NULL)
*seq_num = seq_number;
//[Type 2][PID 8][Data n*2]
log_buffer_get_bytes((CHAR*)user_type, 2, &read_ptr, session->monitor_log);
ULONG64 pid64;
log_buffer_get_bytes((CHAR*)&pid64, 8, &read_ptr, session->monitor_log);
if (user_pid != NULL)
*user_pid = pid64;
log_buffer_get_bytes((CHAR*)user_name, entry_size - (2 + 8), &read_ptr, session->monitor_log);
}
while (*rptr) {
if (first) {
first = FALSE;
*user_type = *rptr;
} else if (name_len) {
*user_name = *rptr;
++user_name;
--name_len;
} else
status = STATUS_BUFFER_OVERFLOW;
++rptr;
if (rptr >= buf0 + SESSION_MONITOR_BUF_SIZE)
rptr = buf0;
}
++rptr;
if (rptr >= buf0 + SESSION_MONITOR_BUF_SIZE)
rptr = buf0;
session->monitor_read_ptr = rptr;
if (name_len)
*user_name = L'\0';
}
// for compatybility with older versions we fall back to clearing the returned entry
if (seq_num != NULL)
log_buffer_pop_entry(session->monitor_log);
}
} __except (EXCEPTION_EXECUTE_HANDLER) {

View File

@ -41,7 +41,7 @@ void Session_Cancel(HANDLE ProcessId);
BOOLEAN Session_IsForceDisabled(ULONG SessionId);
void Session_MonitorPut(USHORT type, const WCHAR *name);
void Session_MonitorPut(USHORT type, const WCHAR *name, HANDLE pid);
//---------------------------------------------------------------------------

View File

@ -1034,7 +1034,7 @@ _FX NTSTATUS Thread_CheckObject_Common(
--nptr; *nptr = L':';
--nptr; *nptr = L'$';
Session_MonitorPut(mon_type, nptr);
Session_MonitorPut(mon_type, nptr, proc->pid);
Mem_Free(nbuf, nlen);
}

View File

@ -58,6 +58,8 @@ DriverAssist::DriverAssist()
m_Threads = NULL;
m_DriverReady = false;
m_last_message_number = 0;
InitializeCriticalSection(&m_LogMessage_CritSec);
InitializeCriticalSection(&m_critSecHostInjectedSvcs);
}

View File

@ -96,7 +96,7 @@ private:
void LogMessage();
void LogMessage_Single(void *data);
void LogMessage_Single(ULONG code, wchar_t* data);
void LogMessage_Multi(ULONG msgid, const WCHAR *path, const WCHAR *text);
void LogMessage_Write(const WCHAR *path, const WCHAR *text);
@ -139,6 +139,8 @@ private:
volatile bool m_DriverReady;
ULONG m_last_message_number;
//
// critical sections
//

View File

@ -50,7 +50,9 @@ void DriverAssist::LogMessage()
break;
ULONG len = m_workItemLen;
ULONG status = SbieApi_GetWork(-1, m_workItemBuf, &len);
ULONG message_number = m_last_message_number;
ULONG code = -1;
ULONG status = SbieApi_GetMessage(&message_number, -1, &code, (wchar_t*)m_workItemBuf, len);
if (status == STATUS_BUFFER_TOO_SMALL) {
HeapFree(GetProcessHeap(), 0, m_workItemBuf);
@ -60,11 +62,16 @@ void DriverAssist::LogMessage()
}
if (status != 0)
break;
break; // error or no more entries
WORK_ITEM *work = (WORK_ITEM *)m_workItemBuf;
if (work->type == API_LOG_MESSAGE)
LogMessage_Single(work->data);
//if (message_number != m_last_message_number + 1)
// we missed something
m_last_message_number = message_number;
if (code == 0)
break; // empty dummy
LogMessage_Single(code, (wchar_t*)m_workItemBuf);
}
if (m_workItemBuf)
@ -79,7 +86,7 @@ void DriverAssist::LogMessage()
//---------------------------------------------------------------------------
void DriverAssist::LogMessage_Single(void *data)
void DriverAssist::LogMessage_Single(ULONG code, wchar_t* data)
{
//
// check if logging is enabled
@ -108,16 +115,15 @@ void DriverAssist::LogMessage_Single(void *data)
// get log message
//
ULONG *msgidptr = (ULONG *)data;
if (*msgidptr == MSG_2199)
if (code == MSG_2199)
return;
WCHAR *str1 = (WCHAR *)(msgidptr + 1);
WCHAR *str1 = data;
ULONG str1_len = wcslen(str1);
WCHAR *str2 = str1 + str1_len + 1;
ULONG str2_len = wcslen(str2);
WCHAR *text = SbieDll_FormatMessage2(*msgidptr, str1, str2);
WCHAR *text = SbieDll_FormatMessage2(code, str1, str2);
if (! text)
return;
@ -152,7 +158,7 @@ void DriverAssist::LogMessage_Single(void *data)
LogMessage_Write(path, text);
LogMessage_Multi(*msgidptr, path, text);
LogMessage_Multi(code, path, text);
LocalFree(text);
}

View File

@ -12,7 +12,7 @@ echo. > %OUTPUT%
for /F "tokens=3*" %%A in ('findstr /R "^#define.SBIE_INSTALLER_PATH\>" %INPUT%') do ( echo ^^!define SBIE_INSTALLER_PATH %%A) >> %OUTPUT%
for /F "tokens=3*" %%A in ('findstr /R "^#define.MY_VERSION_STRING\>" %INPUT%') do ( echo ^^!define VERSION %%A) >> %OUTPUT%
for /F "tokens=3*" %%A in ('findstr /R "^#define.MY_VERSION_STRING_EX\>" %INPUT%') do ( echo ^^!define VERSION %%A) >> %OUTPUT%
for /F "tokens=3*" %%A in ('findstr /R "^#define.MY_PRODUCT_NAME_STRING\>" %INPUT%') do ( set C=%%A %%B& echo ^^!define PRODUCT_FULL_NAME !C! & set C=!C: =!& echo ^^!define PRODUCT_NAME !C!) >> %OUTPUT%

View File

@ -27,8 +27,8 @@ SetCompressor /SOLID /FINAL lzma
;----------------------------------------------------------------------------
; these are the build-time config settings. Need to be cmd line args or something better.
; pick either 32 or 64 bit
!define _BUILDARCH Win32
;!define _BUILDARCH x64
;!define _BUILDARCH Win32
!define _BUILDARCH x64
; uncomment this line if you want to make the special versions that download VC Redist
;!define INCLUDE_VCREDIST_DNLD
@ -764,21 +764,21 @@ FunctionEnd
; We download various files during install just to keep stats on activity
Function DownloadStatPng
Pop $0 ; Get the parameter (file name to download)
${If} ${RunningX64}
SetRegView 64
${EndIf}
ReadRegStr $1 HKLM "SOFTWARE\Microsoft\Cryptography" "MachineGuid"
StrCpy $2 "https://www.sandboxie.com/img/$0?SessionId=$1"
;NSISdl::download_quiet /TIMEOUT=3000 $2 $TEMP\$0
inetc::get /SILENT /CONNECTTIMEOUT=5000 /RECEIVETIMEOUT=5000 $2 $TEMP\$0 /END
Pop $0 ;Get the return value
;MessageBox MB_OK|MB_ICONSTOP "DownloadStatPng: $2$\n$0"
${If} ${RunningX64}
SetRegView 32
${EndIf}
;
; Pop $0 ; Get the parameter (file name to download)
; ${If} ${RunningX64}
; SetRegView 64
; ${EndIf}
; ReadRegStr $1 HKLM "SOFTWARE\Microsoft\Cryptography" "MachineGuid"
; StrCpy $2 "https://www.sandboxie.com/img/$0?SessionId=$1"
;
; ;NSISdl::download_quiet /TIMEOUT=3000 $2 $TEMP\$0
; inetc::get /SILENT /CONNECTTIMEOUT=5000 /RECEIVETIMEOUT=5000 $2 $TEMP\$0 /END
; Pop $0 ;Get the return value
; ;MessageBox MB_OK|MB_ICONSTOP "DownloadStatPng: $2$\n$0"
; ${If} ${RunningX64}
; SetRegView 32
; ${EndIf}
FunctionEnd

View File

@ -70,9 +70,7 @@
</ImportGroup>
<PropertyGroup Label="UserMacros" />
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='SbieDebug|Win32'" />
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='SbieDebug|x64'">
<LibraryPath>$(WDKPATH)\lib\crt\amd64;$(LibraryPath)</LibraryPath>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='SbieDebug|x64'" />
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='SbieRelease|Win32'" />
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='SbieRelease|x64'" />
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='SbieDebug|Win32'">

View File

@ -0,0 +1,235 @@
#include "stdafx.h"
#include "CheckableMessageBox.h"
#include <QPushButton>
#include <QCheckBox>
#include <QHBoxLayout>
#include <QLabel>
#include <QDebug>
/*!
\class Utils::CCheckableMessageBox
\brief A messagebox suitable for questions with a
"Do not ask me again" checkbox.
Emulates the QMessageBox API with
static conveniences. The message label can open external URLs.
*/
class CCheckableMessageBoxPrivate
{
public:
CCheckableMessageBoxPrivate(QDialog *q)
: clickedButton(0)
{
QSizePolicy sizePolicy(QSizePolicy::Minimum, QSizePolicy::Preferred);
pixmapLabel = new QLabel(q);
sizePolicy.setHorizontalStretch(0);
sizePolicy.setVerticalStretch(0);
sizePolicy.setHeightForWidth(pixmapLabel->sizePolicy().hasHeightForWidth());
pixmapLabel->setSizePolicy(sizePolicy);
pixmapLabel->setVisible(false);
QSpacerItem *pixmapSpacer =
new QSpacerItem(0, 5, QSizePolicy::Minimum, QSizePolicy::MinimumExpanding);
messageLabel = new QLabel(q);
messageLabel->setMinimumSize(QSize(300, 0));
messageLabel->setSizePolicy(QSizePolicy::Expanding, messageLabel->sizePolicy().verticalPolicy());
messageLabel->setWordWrap(true);
messageLabel->setOpenExternalLinks(true);
messageLabel->setTextInteractionFlags(Qt::LinksAccessibleByKeyboard|Qt::LinksAccessibleByMouse);
QSpacerItem *checkBoxRightSpacer =
new QSpacerItem(1, 1, QSizePolicy::Expanding, QSizePolicy::Minimum);
QSpacerItem *buttonSpacer =
new QSpacerItem(0, 1, QSizePolicy::Minimum, QSizePolicy::Minimum);
checkBox = new QCheckBox(q);
checkBox->setText(CCheckableMessageBox::tr("Do not ask again"));
buttonBox = new QDialogButtonBox(q);
buttonBox->setOrientation(Qt::Horizontal);
buttonBox->setStandardButtons(QDialogButtonBox::Cancel|QDialogButtonBox::Ok);
QVBoxLayout *verticalLayout = new QVBoxLayout();
verticalLayout->addWidget(pixmapLabel);
verticalLayout->addItem(pixmapSpacer);
QHBoxLayout *horizontalLayout_2 = new QHBoxLayout();
horizontalLayout_2->addLayout(verticalLayout);
horizontalLayout_2->addWidget(messageLabel);
QHBoxLayout *horizontalLayout = new QHBoxLayout();
horizontalLayout->addWidget(checkBox);
horizontalLayout->addItem(checkBoxRightSpacer);
QVBoxLayout *verticalLayout_2 = new QVBoxLayout(q);
verticalLayout_2->addLayout(horizontalLayout_2);
verticalLayout_2->addLayout(horizontalLayout);
verticalLayout_2->addItem(buttonSpacer);
verticalLayout_2->addWidget(buttonBox);
}
QLabel *pixmapLabel;
QLabel *messageLabel;
QCheckBox *checkBox;
QDialogButtonBox *buttonBox;
QAbstractButton *clickedButton;
};
CCheckableMessageBox::CCheckableMessageBox(QWidget *parent) :
QDialog(parent),
d(new CCheckableMessageBoxPrivate(this))
{
setModal(true);
setWindowFlags(windowFlags() & ~Qt::WindowContextHelpButtonHint);
connect(d->buttonBox, SIGNAL(accepted()), SLOT(accept()));
connect(d->buttonBox, SIGNAL(rejected()), SLOT(reject()));
connect(d->buttonBox, SIGNAL(clicked(QAbstractButton*)),
SLOT(slotClicked(QAbstractButton*)));
}
CCheckableMessageBox::~CCheckableMessageBox()
{
delete d;
}
void CCheckableMessageBox::slotClicked(QAbstractButton *b)
{
d->clickedButton = b;
}
QAbstractButton *CCheckableMessageBox::clickedButton() const
{
return d->clickedButton;
}
QDialogButtonBox::StandardButton CCheckableMessageBox::clickedStandardButton() const
{
if (d->clickedButton)
return d->buttonBox->standardButton(d->clickedButton);
return QDialogButtonBox::NoButton;
}
QString CCheckableMessageBox::text() const
{
return d->messageLabel->text();
}
void CCheckableMessageBox::setText(const QString &t)
{
d->messageLabel->setText(t);
}
QPixmap CCheckableMessageBox::iconPixmap() const
{
if (const QPixmap *p = d->pixmapLabel->pixmap())
return QPixmap(*p);
return QPixmap();
}
void CCheckableMessageBox::setIconPixmap(const QPixmap &p)
{
d->pixmapLabel->setPixmap(p);
d->pixmapLabel->setVisible(!p.isNull());
}
bool CCheckableMessageBox::isChecked() const
{
return d->checkBox->isChecked();
}
void CCheckableMessageBox::setChecked(bool s)
{
d->checkBox->setChecked(s);
}
QString CCheckableMessageBox::checkBoxText() const
{
return d->checkBox->text();
}
void CCheckableMessageBox::setCheckBoxText(const QString &t)
{
d->checkBox->setText(t);
}
bool CCheckableMessageBox::isCheckBoxVisible() const
{
return d->checkBox->isVisible();
}
void CCheckableMessageBox::setCheckBoxVisible(bool v)
{
d->checkBox->setVisible(v);
}
QDialogButtonBox::StandardButtons CCheckableMessageBox::standardButtons() const
{
return d->buttonBox->standardButtons();
}
void CCheckableMessageBox::setStandardButtons(QDialogButtonBox::StandardButtons s)
{
d->buttonBox->setStandardButtons(s);
}
QPushButton *CCheckableMessageBox::button(QDialogButtonBox::StandardButton b) const
{
return d->buttonBox->button(b);
}
QPushButton *CCheckableMessageBox::addButton(const QString &text, QDialogButtonBox::ButtonRole role)
{
return d->buttonBox->addButton(text, role);
}
QDialogButtonBox::StandardButton CCheckableMessageBox::defaultButton() const
{
foreach (QAbstractButton *b, d->buttonBox->buttons())
if (QPushButton *pb = qobject_cast<QPushButton *>(b))
if (pb->isDefault())
return d->buttonBox->standardButton(pb);
return QDialogButtonBox::NoButton;
}
void CCheckableMessageBox::setDefaultButton(QDialogButtonBox::StandardButton s)
{
if (QPushButton *b = d->buttonBox->button(s)) {
b->setDefault(true);
b->setFocus();
}
}
QDialogButtonBox::StandardButton
CCheckableMessageBox::question(QWidget *parent,
const QString &title,
const QString &question,
const QString &checkBoxText,
bool *checkBoxSetting,
QDialogButtonBox::StandardButtons buttons,
QDialogButtonBox::StandardButton defaultButton,
QMessageBox::Icon icon)
{
CCheckableMessageBox mb(parent);
mb.setWindowTitle(title);
mb.setIconPixmap(QMessageBox::standardIcon(icon));
mb.setText(question);
mb.setCheckBoxText(checkBoxText);
mb.setChecked(*checkBoxSetting);
mb.setStandardButtons(buttons);
mb.setDefaultButton(defaultButton);
mb.exec();
*checkBoxSetting = mb.isChecked();
return mb.clickedStandardButton();
}
QMessageBox::StandardButton CCheckableMessageBox::dialogButtonBoxToMessageBoxButton(QDialogButtonBox::StandardButton db)
{
return static_cast<QMessageBox::StandardButton>(int(db));
}

View File

@ -0,0 +1,75 @@
#ifndef CHECKABLEMESSAGEBOX_H
#define CHECKABLEMESSAGEBOX_H
#include <QDialogButtonBox>
#include <QMessageBox>
class CCheckableMessageBoxPrivate;
#include "../mischelpers_global.h"
class MISCHELPERS_EXPORT CCheckableMessageBox : public QDialog
{
Q_OBJECT
Q_PROPERTY(QString text READ text WRITE setText)
Q_PROPERTY(QPixmap iconPixmap READ iconPixmap WRITE setIconPixmap)
Q_PROPERTY(bool isChecked READ isChecked WRITE setChecked)
Q_PROPERTY(QString checkBoxText READ checkBoxText WRITE setCheckBoxText)
Q_PROPERTY(QDialogButtonBox::StandardButtons buttons READ standardButtons WRITE setStandardButtons)
Q_PROPERTY(QDialogButtonBox::StandardButton defaultButton READ defaultButton WRITE setDefaultButton)
public:
explicit CCheckableMessageBox(QWidget *parent = NULL);
virtual ~CCheckableMessageBox();
static QDialogButtonBox::StandardButton
question(QWidget *parent,
const QString &title,
const QString &question,
const QString &checkBoxText,
bool *checkBoxSetting,
QDialogButtonBox::StandardButtons buttons = QDialogButtonBox::Yes|QDialogButtonBox::No,
QDialogButtonBox::StandardButton defaultButton = QDialogButtonBox::No,
QMessageBox::Icon icon = QMessageBox::Question);
QString text() const;
void setText(const QString &);
bool isChecked() const;
void setChecked(bool s);
QString checkBoxText() const;
void setCheckBoxText(const QString &);
bool isCheckBoxVisible() const;
void setCheckBoxVisible(bool);
QDialogButtonBox::StandardButtons standardButtons() const;
void setStandardButtons(QDialogButtonBox::StandardButtons s);
QPushButton *button(QDialogButtonBox::StandardButton b) const;
QPushButton *addButton(const QString &text, QDialogButtonBox::ButtonRole role);
QDialogButtonBox::StandardButton defaultButton() const;
void setDefaultButton(QDialogButtonBox::StandardButton s);
// See static QMessageBox::standardPixmap()
QPixmap iconPixmap() const;
void setIconPixmap (const QPixmap &p);
// Query the result
QAbstractButton *clickedButton() const;
QDialogButtonBox::StandardButton clickedStandardButton() const;
// Conversion convenience
static QMessageBox::StandardButton dialogButtonBoxToMessageBoxButton(QDialogButtonBox::StandardButton);
private slots:
void slotClicked(QAbstractButton *b);
private:
CCheckableMessageBoxPrivate *d;
};
#endif // CHECKABLEMESSAGEBOX_H

View File

@ -0,0 +1,193 @@
#include "stdafx.h"
#include "ComboInputDialog.h"
#include <QPushButton>
#include <QCheckBox>
#include <QHBoxLayout>
#include <QLabel>
#include <QDebug>
class CComboInputDialogPrivate
{
public:
CComboInputDialogPrivate(QDialog *q)
: clickedButton(0)
{
QSizePolicy sizePolicy(QSizePolicy::Minimum, QSizePolicy::Preferred);
pixmapLabel = new QLabel(q);
sizePolicy.setHorizontalStretch(0);
sizePolicy.setVerticalStretch(0);
sizePolicy.setHeightForWidth(pixmapLabel->sizePolicy().hasHeightForWidth());
pixmapLabel->setSizePolicy(sizePolicy);
pixmapLabel->setVisible(false);
QSpacerItem *pixmapSpacer =
new QSpacerItem(0, 5, QSizePolicy::Minimum, QSizePolicy::MinimumExpanding);
messageLabel = new QLabel(q);
messageLabel->setMinimumSize(QSize(300, 0));
messageLabel->setWordWrap(true);
messageLabel->setOpenExternalLinks(true);
messageLabel->setTextInteractionFlags(Qt::LinksAccessibleByKeyboard|Qt::LinksAccessibleByMouse);
QSpacerItem *buttonSpacer =
new QSpacerItem(0, 1, QSizePolicy::Minimum, QSizePolicy::Minimum);
combo = new QComboBox(q);
buttonBox = new QDialogButtonBox(q);
buttonBox->setOrientation(Qt::Horizontal);
buttonBox->setStandardButtons(QDialogButtonBox::Cancel|QDialogButtonBox::Ok);
QVBoxLayout *verticalLayout = new QVBoxLayout();
verticalLayout->addWidget(pixmapLabel);
verticalLayout->addItem(pixmapSpacer);
QHBoxLayout *horizontalLayout_2 = new QHBoxLayout();
horizontalLayout_2->addLayout(verticalLayout);
horizontalLayout_2->addWidget(messageLabel);
QVBoxLayout *verticalLayout_2 = new QVBoxLayout(q);
verticalLayout_2->addLayout(horizontalLayout_2);
verticalLayout_2->addWidget(combo);
verticalLayout_2->addItem(buttonSpacer);
verticalLayout_2->addWidget(buttonBox);
}
QLabel *pixmapLabel;
QLabel *messageLabel;
QComboBox* combo;
QDialogButtonBox *buttonBox;
QAbstractButton *clickedButton;
};
CComboInputDialog::CComboInputDialog(QWidget *parent) :
QDialog(parent),
d(new CComboInputDialogPrivate(this))
{
setModal(true);
setWindowFlags(windowFlags() & ~Qt::WindowContextHelpButtonHint);
connect(d->buttonBox, SIGNAL(accepted()), SLOT(accept()));
connect(d->buttonBox, SIGNAL(rejected()), SLOT(reject()));
connect(d->buttonBox, SIGNAL(clicked(QAbstractButton*)),
SLOT(slotClicked(QAbstractButton*)));
}
CComboInputDialog::~CComboInputDialog()
{
delete d;
}
void CComboInputDialog::slotClicked(QAbstractButton *b)
{
d->clickedButton = b;
}
QAbstractButton *CComboInputDialog::clickedButton() const
{
return d->clickedButton;
}
QDialogButtonBox::StandardButton CComboInputDialog::clickedStandardButton() const
{
if (d->clickedButton)
return d->buttonBox->standardButton(d->clickedButton);
return QDialogButtonBox::NoButton;
}
QString CComboInputDialog::text() const
{
return d->messageLabel->text();
}
void CComboInputDialog::setText(const QString &t)
{
d->messageLabel->setText(t);
}
void CComboInputDialog::addItem(const QString& t, const QVariant & v)
{
d->combo->addItem(t, v);
}
void CComboInputDialog::setEditable(bool b)
{
d->combo->setEditable(b);
}
QString CComboInputDialog::value() const
{
return d->combo->currentText();
}
void CComboInputDialog::setValue(const QString &t)
{
int idx = d->combo->findText(t);
if(idx == -1)
d->combo->setEditText(t);
else
d->combo->setCurrentIndex(idx);
}
QVariant CComboInputDialog::data() const
{
return d->combo->currentData();
}
void CComboInputDialog::setData(const QVariant & v)
{
d->combo->setCurrentIndex(d->combo->findData(v));
}
QPixmap CComboInputDialog::iconPixmap() const
{
if (const QPixmap *p = d->pixmapLabel->pixmap())
return QPixmap(*p);
return QPixmap();
}
void CComboInputDialog::setIconPixmap(const QPixmap &p)
{
d->pixmapLabel->setPixmap(p);
d->pixmapLabel->setVisible(!p.isNull());
}
QDialogButtonBox::StandardButtons CComboInputDialog::standardButtons() const
{
return d->buttonBox->standardButtons();
}
void CComboInputDialog::setStandardButtons(QDialogButtonBox::StandardButtons s)
{
d->buttonBox->setStandardButtons(s);
}
QPushButton *CComboInputDialog::button(QDialogButtonBox::StandardButton b) const
{
return d->buttonBox->button(b);
}
QPushButton *CComboInputDialog::addButton(const QString &text, QDialogButtonBox::ButtonRole role)
{
return d->buttonBox->addButton(text, role);
}
QDialogButtonBox::StandardButton CComboInputDialog::defaultButton() const
{
foreach (QAbstractButton *b, d->buttonBox->buttons())
if (QPushButton *pb = qobject_cast<QPushButton *>(b))
if (pb->isDefault())
return d->buttonBox->standardButton(pb);
return QDialogButtonBox::NoButton;
}
void CComboInputDialog::setDefaultButton(QDialogButtonBox::StandardButton s)
{
if (QPushButton *b = d->buttonBox->button(s)) {
b->setDefault(true);
b->setFocus();
}
}

View File

@ -0,0 +1,61 @@
#ifndef HCOMBOINPUTDIALOG_H
#define HCOMBOINPUTDIALOG_H
#include <QDialogButtonBox>
#include <QMessageBox>
class CComboInputDialogPrivate;
#include "../mischelpers_global.h"
class MISCHELPERS_EXPORT CComboInputDialog: public QDialog
{
Q_OBJECT
Q_PROPERTY(QString text READ text WRITE setText)
Q_PROPERTY(QPixmap iconPixmap READ iconPixmap WRITE setIconPixmap)
Q_PROPERTY(QDialogButtonBox::StandardButtons buttons READ standardButtons WRITE setStandardButtons)
Q_PROPERTY(QDialogButtonBox::StandardButton defaultButton READ defaultButton WRITE setDefaultButton)
public:
explicit CComboInputDialog(QWidget *parent = NULL);
virtual ~CComboInputDialog();
QString text() const;
void setText(const QString &);
void addItem(const QString&, const QVariant & = QVariant());
void setEditable(bool);
QString value() const;
void setValue(const QString &);
QVariant data() const;
void setData(const QVariant &);
QDialogButtonBox::StandardButtons standardButtons() const;
void setStandardButtons(QDialogButtonBox::StandardButtons s);
QPushButton *button(QDialogButtonBox::StandardButton b) const;
QPushButton *addButton(const QString &text, QDialogButtonBox::ButtonRole role);
QDialogButtonBox::StandardButton defaultButton() const;
void setDefaultButton(QDialogButtonBox::StandardButton s);
// See static QMessageBox::standardPixmap()
QPixmap iconPixmap() const;
void setIconPixmap (const QPixmap &p);
// Query the result
QAbstractButton *clickedButton() const;
QDialogButtonBox::StandardButton clickedStandardButton() const;
private slots:
void slotClicked(QAbstractButton *b);
private:
CComboInputDialogPrivate *d;
};
#endif // HCOMBOINPUTDIALOG_H

View File

@ -0,0 +1,321 @@
#include "stdafx.h"
#include "Common.h"
#ifdef USE_OPENSSL
#include <openssl/rand.h>
#endif
#ifndef WIN32 // vswprintf
#include <stdio.h>
#include <stdarg.h>
int vswprintf_l(wchar_t * _String, size_t _Count, const wchar_t * _Format, va_list _Ap)
{
wchar_t _Format_l[1025];
ASSERT(wcslen(_Format) < 1024);
wcscpy(_Format_l, _Format);
for(int i=0; i<wcslen(_Format_l); i++)
{
if(_Format_l[i] == L'%')
{
switch(_Format_l[i+1])
{
case L's': _Format_l[i+1] = 'S'; break;
case L'S': _Format_l[i+1] = 's'; break;
}
}
}
return vswprintf(_String, _Count, _Format_l, _Ap);
}
#endif
//////////////////////////////////////////////////////////////////////////////////////////
// Time Functions
//
time_t GetTime()
{
QDateTime dateTime = QDateTime::currentDateTime();
time_t time = dateTime.toTime_t(); // returns time in seconds (since 1970-01-01T00:00:00) in UTC !
return time;
}
struct SCurTick
{
SCurTick() {Timer.start();}
quint64 Get(){return Timer.elapsed();}
QElapsedTimer Timer;
} g_CurTick;
quint64 GetCurTick()
{
return g_CurTick.Get();
}
QString UnEscape(QString Text)
{
QString Value;
bool bEsc = false;
for(int i = 0; i < Text.size(); i++)
{
QChar Char = Text.at(i);
if(bEsc)
{
switch(Char.unicode())
{
case L'\\': Value += L'\\'; break;
case L'\'': Value += L'\''; break;
case L'\"': Value += L'\"'; break;
case L'a': Value += L'\a'; break;
case L'b': Value += L'\b'; break;
case L'f': Value += L'\f'; break;
case L'n': Value += L'\n'; break;
case L'r': Value += L'\r'; break;
case L't': Value += L'\t'; break;
case L'v': Value += L'\v'; break;
default: Value += Char.unicode();break;
}
bEsc = false;
}
else if(Char == L'\\')
bEsc = true;
else
Value += Char;
}
return Value;
}
//////////////////////////////////////////////////////////////////////////////////////////
// Other Functions
//
quint64 GetRand64()
{
quint64 Rand64;
#ifdef USE_OPENSSL
int Ret = RAND_bytes((byte*)&Rand64, sizeof(uint64));
ASSERT(Ret == 1); // An error occurs if the PRNG has not been seeded with enough randomness to ensure an unpredictable byte sequence.
#else
//CryptoPP::AutoSeededRandomPool rng;
//rng.GenerateBlock((byte*)&Rand64, sizeof(quint64));
Rand64 = QRandomGenerator::system()->generate64();
#endif
return Rand64;
}
QString GetRand64Str(bool forUrl)
{
quint64 Rand64 = GetRand64();
QString sRand64 = QByteArray((char*)&Rand64,sizeof(quint64)).toBase64();
if(forUrl)
sRand64.replace("+","-").replace("/","_");
return sRand64.replace("=","");
}
int GetRandomInt(int iMin, int iMax)
{
return QRandomGenerator::system()->bounded(iMin, iMax);
}
StrPair Split2(const QString& String, QString Separator, bool Back)
{
int Sep = Back ? String.lastIndexOf(Separator) : String.indexOf(Separator);
if(Sep != -1)
return qMakePair(String.left(Sep).trimmed(), String.mid(Sep+Separator.length()).trimmed());
return qMakePair(String.trimmed(), QString());
}
QStringList SplitStr(const QString& String, QString Separator)
{
QStringList List = String.split(Separator);
for(int i=0; i < List.count(); i++)
{
List[i] = List[i].trimmed();
if(List[i].isEmpty())
List.removeAt(i--);
}
return List;
}
QString FormatSize(quint64 Size, int Precision)
{
double Div;
if(Size > (quint64)(Div = 1.0*1024*1024*1024*1024*1024*1024))
return QString::number(double(Size)/Div, 'f', Precision) + " EB";
if(Size > (quint64)(Div = 1.0*1024*1024*1024*1024*1024))
return QString::number(double(Size)/Div, 'f', Precision) + " PB";
if(Size > (quint64)(Div = 1.0*1024*1024*1024*1024))
return QString::number(double(Size)/Div, 'f', Precision) + " TB";
if(Size > (quint64)(Div = 1.0*1024*1024*1024))
return QString::number(double(Size)/Div, 'f', Precision) + " GB";
if(Size > (quint64)(Div = 1.0*1024*1024))
return QString::number(double(Size)/Div, 'f', Precision) + " MB";
if(Size > (quint64)(Div = 1.0*1024))
return QString::number(double(Size)/Div, 'f', Precision) + " KB";
return QString::number(double(Size)) + "B";
}
QString FormatRate(quint64 Size, int Precision)
{
return FormatSize(Size, Precision) + "/s";
}
QString FormatUnit(quint64 Size, int Precision)
{
double Div;
if(Size > (quint64)(Div = 1.0*1000*1000*1000*1024*1000*1000))
return QString::number(double(Size)/Div, 'f', Precision) + " E";
if(Size > (quint64)(Div = 1.0*1000*1000*1000*1000*1000))
return QString::number(double(Size)/Div, 'f', Precision) + " P";
if(Size > (quint64)(Div = 1.0*1000*1000*1000*1000))
return QString::number(double(Size)/Div, 'f', Precision) + " T";
if(Size > (quint64)(Div = 1.0*1000*1000*1000))
return QString::number(double(Size)/Div, 'f', Precision) + " G";
if(Size > (quint64)(Div = 1.0*1000*1000))
return QString::number(double(Size)/Div, 'f', Precision) + " M";
if(Size > (quint64)(Div = 1.0*1000))
return QString::number(double(Size)/Div, 'f', Precision) + " K";
return QString::number(double(Size));
}
QString FormatTime(quint64 Time, bool ms)
{
int miliseconds = 0;
if (ms) {
miliseconds = Time % 1000;
Time /= 1000;
}
int seconds = Time % 60;
Time /= 60;
int minutes = Time % 60;
Time /= 60;
int hours = Time % 24;
int days = Time / 24;
if(ms && (minutes == 0) && (hours == 0) && (days == 0))
return QString().sprintf("%02d.%04d", seconds, miliseconds);
if((hours == 0) && (days == 0))
return QString().sprintf("%02d:%02d", minutes, seconds);
if (days == 0)
return QString().sprintf("%02d:%02d:%02d", hours, minutes, seconds);
return QString().sprintf("%dd%02d:%02d:%02d", days, hours, minutes, seconds);
}
QString FormatNumber(quint64 Number)
{
QString String = QString::number(Number);
for (int i = String.length() - 3; i > 0; i -= 3)
String.insert(i, QString::fromWCharArray(L"\u202F")); // L"\u2009"
return String;
}
QString FormatAddress(quint64 Address, int length)
{
return "0x" + QString::number(Address, 16).rightJustified(length, '0');
}
bool ReadFromDevice(QIODevice* dev, char* data, int len, int timeout)
{
while (dev->bytesAvailable() < len) {
if (!dev->waitForReadyRead(timeout))
return false;
}
return dev->read(data, len) == len;
}
void GrayScale (QImage& Image)
{
if (Image.depth () == 32)
{
uchar* r = (Image.bits ());
uchar* g = (Image.bits () + 1);
uchar* b = (Image.bits () + 2);
uchar* end = (Image.bits() + Image.byteCount ());
while (r != end)
{
*r = *g = *b = (((*r + *g) >> 1) + *b) >> 1; // (r + b + g) / 3
r += 4;
g += 4;
b += 4;
}
}
else
{
for (int i = 0; i < Image.colorCount (); i++)
{
uint r = qRed (Image.color (i));
uint g = qGreen (Image.color (i));
uint b = qBlue (Image.color (i));
uint gray = (((r + g) >> 1) + b) >> 1;
Image.setColor (i, qRgba (gray, gray, gray, qAlpha (Image.color (i))));
}
}
}
QIcon MakeActionIcon(const QString& IconFile)
{
QImage Image(IconFile);
QIcon Icon;
Icon.addPixmap(QPixmap::fromImage(Image), QIcon::Normal);
GrayScale(Image);
Icon.addPixmap(QPixmap::fromImage(Image), QIcon::Disabled);
return Icon;
}
QAction* MakeAction(QToolBar* pParent, const QString& IconFile, const QString& Text)
{
QAction* pAction = new QAction(Text, pParent);
pAction->setIcon(MakeActionIcon(IconFile));
pParent->addAction(pAction);
return pAction;
}
QMenu* MakeMenu(QMenu* pParent, const QString& Text, const QString& IconFile)
{
if(!IconFile.isEmpty())
{
QImage Image(IconFile);
QIcon Icon;
Icon.addPixmap(QPixmap::fromImage(Image), QIcon::Normal);
GrayScale(Image);
Icon.addPixmap(QPixmap::fromImage(Image), QIcon::Disabled);
return pParent->addMenu(Icon, Text);
}
return pParent->addMenu(Text);
}
QAction* MakeAction(QMenu* pParent, const QString& Text, const QString& IconFile)
{
QAction* pAction = new QAction(Text, pParent);
if(!IconFile.isEmpty())
{
QImage Image(IconFile);
QIcon Icon;
Icon.addPixmap(QPixmap::fromImage(Image), QIcon::Normal);
GrayScale(Image);
Icon.addPixmap(QPixmap::fromImage(Image), QIcon::Disabled);
pAction->setIcon(Icon);
}
pParent->addAction(pAction);
return pAction;
}
QAction* MakeAction(QActionGroup* pGroup, QMenu* pParent, const QString& Text, const QVariant& Data)
{
QAction* pAction = new QAction(Text, pParent);
pAction->setCheckable(true);
pAction->setData(Data);
pAction->setActionGroup(pGroup);
pParent->addAction(pAction);
return pAction;
}

View File

@ -0,0 +1,92 @@
#pragma once
#include "../mischelpers_global.h"
#ifndef WIN32
MISCHELPERS_EXPORT int vswprintf_l(wchar_t * _String, size_t _Count, const wchar_t * _Format, va_list _Ap);
#endif
MISCHELPERS_EXPORT time_t GetTime();
MISCHELPERS_EXPORT quint64 GetCurTick();
MISCHELPERS_EXPORT quint64 GetRand64();
MISCHELPERS_EXPORT QString GetRand64Str(bool forUrl = true);
MISCHELPERS_EXPORT int GetRandomInt(int iMin, int iMax);
MISCHELPERS_EXPORT typedef QPair<QString,QString> StrPair;
MISCHELPERS_EXPORT StrPair Split2(const QString& String, QString Separator = "=", bool Back = false);
MISCHELPERS_EXPORT QStringList SplitStr(const QString& String, QString Separator);
MISCHELPERS_EXPORT QString UnEscape(QString Text);
MISCHELPERS_EXPORT QString FormatSize(quint64 Size, int Precision = 2);
__inline QString FormatSizeEx(quint64 Size, bool bEx) { return bEx && (Size == 0) ? QString() : FormatSize(Size); }
MISCHELPERS_EXPORT QString FormatRate(quint64 Size, int Precision = 2);
__inline QString FormatRateEx(quint64 Size, bool bEx) { return bEx && (Size == 0) ? QString() : FormatRate(Size); }
MISCHELPERS_EXPORT QString FormatUnit(quint64 Size, int Precision = 0);
MISCHELPERS_EXPORT QString FormatTime(quint64 Time, bool ms = false);
MISCHELPERS_EXPORT QString FormatNumber(quint64 Number);
__inline QString FormatNumberEx(quint64 Number, bool bEx) { return bEx && (Number == 0) ? QString() : FormatNumber(Number); }
MISCHELPERS_EXPORT QString FormatAddress(quint64 Address, int length = 16);
inline bool operator < (const QHostAddress &key1, const QHostAddress &key2)
{
// Note: toIPv6Address also works for IPv4 addresses
Q_IPV6ADDR ip1 = key1.toIPv6Address();
Q_IPV6ADDR ip2 = key2.toIPv6Address();
return memcmp(&ip1, &ip2, sizeof(Q_IPV6ADDR)) < 0;
}
template <typename T>
QVariantList toVariantList( const QList<T> &list )
{
QVariantList newList;
foreach( const T &item, list )
newList << item;
return newList;
}
template <typename T>
QList<T> reversed( const QList<T> & in ) {
QList<T> result;
result.reserve( in.size() ); // reserve is new in Qt 4.7
std::reverse_copy( in.begin(), in.end(), std::back_inserter( result ) );
return result;
}
template <class T>
class CScoped
{
public:
CScoped(T* Val = NULL) {m_Val = Val;}
~CScoped() {delete m_Val;}
CScoped<T>& operator=(const CScoped<T>& Scoped) {ASSERT(0); return *this;} // copying is explicitly forbidden
CScoped<T>& operator=(T* Val) {ASSERT(!m_Val); m_Val = Val; return *this;}
inline T* Val() const {return m_Val;}
inline T* &Val() {return m_Val;}
inline T* Detache() {T* Val = m_Val; m_Val = NULL; return Val;}
inline T* operator->() const {return m_Val;}
inline T& operator*() const {return *m_Val;}
inline operator T*() const {return m_Val;}
private:
T* m_Val;
};
MISCHELPERS_EXPORT bool ReadFromDevice(QIODevice* dev, char* data, int len, int timeout = 5000);
MISCHELPERS_EXPORT void GrayScale (QImage& Image);
MISCHELPERS_EXPORT QIcon MakeActionIcon(const QString& IconFile);
MISCHELPERS_EXPORT QAction* MakeAction(QToolBar* pParent, const QString& IconFile, const QString& Text = "");
MISCHELPERS_EXPORT QMenu* MakeMenu(QMenu* pParent, const QString& Text, const QString& IconFile = "");
MISCHELPERS_EXPORT QAction* MakeAction(QMenu* pParent, const QString& Text, const QString& IconFile = "");
MISCHELPERS_EXPORT QAction* MakeAction(QActionGroup* pGroup, QMenu* pParent, const QString& Text, const QVariant& Data);

View File

@ -0,0 +1,391 @@
#include "stdafx.h"
#include "DebugHelpers.h"
#include "Common.h"
#include <QDebug>
#ifdef WIN32
#include <windows.h>
#endif
bool IsDebuggerAttached()
{
bool isDebuggerPresent = false; // Note: on linux change edit the value in debgger to indicate precense
#ifdef WIN32
if (IsDebuggerPresent())
return true;
#endif
return isDebuggerPresent;
}
void WaitForDebugger()
{
while (!IsDebuggerAttached())
QThread::msleep(500);
}
#if defined(_DEBUG) || defined(_TRACE)
#ifdef WIN32
bool g_assert_active = IsDebuggerPresent();
#else
bool g_assert_active = true;
#endif
void Assert(bool test)
{
if(!test && g_assert_active)
_CrtDbgBreak();
}
void CTracer::operator()(const QString &sLine) const
{
qDebug() << sLine;
}
void CTracer::operator()(const wchar_t *sLine, ...) const
{
const size_t bufferSize = 10241;
wchar_t bufferline[bufferSize];
va_list argptr;
va_start(argptr, sLine);
#ifndef WIN32
if (vswprintf_l(bufferline, bufferSize, sLine, argptr) == -1)
#else
if (vswprintf(bufferline, bufferSize, sLine, argptr) == -1)
#endif
bufferline[bufferSize - 1] = L'\0';
va_end(argptr);
QString sBufferLine = QString::fromWCharArray(bufferline);
qDebug() << sBufferLine;
}
void CTracer::operator()(const char *sLine, ...) const
{
const size_t bufferSize = 10241;
char bufferline[bufferSize];
va_list argptr;
va_start(argptr, sLine);
if (vsprintf(bufferline, sLine, argptr) == -1)
bufferline[bufferSize - 1] = L'\0';
va_end(argptr);
QString sBufferLine = bufferline;
qDebug() << sBufferLine;
}
////////////////////////////////////////////////////////////////////////////////////////////
// Tracers
////////////////////////////////////////////////////////////////////////////////////////////
CMemTracer memTracer;
void CMemTracer::DumpTrace()
{
QMutexLocker Locker(&m_Locker);
for(map<string,int>::iterator I = m_MemoryTrace.begin(); I != m_MemoryTrace.end(); I++)
{
map<string,int>::iterator J = m_MemoryTrace2.find(I->first);
if(J != m_MemoryTrace2.end())
TRACE(L"MEMORY TRACE: Object '%S' has %d (%d) instances.",I->first.c_str(),I->second, J->second);
else
TRACE(L"MEMORY TRACE: Object '%S' has %d instances.",I->first.c_str(),I->second);
}
}
void CMemTracer::TraceAlloc(string Name)
{
QMutexLocker Locker(&m_Locker);
m_MemoryTrace[Name] += 1;
}
void CMemTracer::TraceFree(string Name)
{
QMutexLocker Locker(&m_Locker);
m_MemoryTrace[Name] -= 1;
//if(m_MemoryTrace2[Name] > 0)
if(m_MemoryTrace2.find(Name) != m_MemoryTrace2.end())
m_MemoryTrace2[Name] -= 1;
}
void CMemTracer::TracePre(string Name)
{
QMutexLocker Locker(&m_Locker);
m_MemoryTrace2[Name] += 1;
}
/////////////////////////////////////////////////////////////////////////////////////
CCpuTracer cpuTracer;
void CCpuTracer::DumpTrace()
{
QMutexLocker Locker(&m_Locker);
for(map<string,SCycles>::iterator I = m_CpuUsageTrace.begin(); I != m_CpuUsageTrace.end(); I++)
TRACE(L"CPU TRACE: Prozedure '%S' needed %f seconds.",I->first.c_str(),(double)I->second.Total/1000000.0);
}
void CCpuTracer::ResetTrace()
{
QMutexLocker Locker(&m_Locker);
m_CpuUsageTrace.clear();
}
void CCpuTracer::TraceStart(string Name)
{
QMutexLocker Locker(&m_Locker);
m_CpuUsageTrace[Name].Counting = GetCurCycle();
}
void CCpuTracer::TraceStop(string Name)
{
QMutexLocker Locker(&m_Locker);
m_CpuUsageTrace[Name].Total += GetCurCycle() - m_CpuUsageTrace[Name].Counting;
}
/////////////////////////////////////////////////////////////////////////////////////
CLockTracer lockTracer;
void CLockTracer::DumpTrace()
{
QMutexLocker Locker(&m_Locker);
for(map<string,SLocks>::iterator I = m_LockTrace.begin(); I != m_LockTrace.end(); I++)
TRACE(L"LOCK TRACE: Lock '%S' has %d Locks for %f seconds.",I->first.c_str(),I->second.LockCount, (double)(GetCurCycle()/1000 - I->second.LockTime) / 1000);
}
void CLockTracer::TraceLock(string Name, int op)
{
QMutexLocker Locker(&m_Locker);
SLocks &Locks = m_LockTrace[Name];
if(Locks.LockCount == 0)
Locks.LockTime = GetCurCycle()/1000;
Locks.LockCount += op;
if(Locks.LockCount == 0)
Locks.LockTime = 0;
}
#endif
/////////////////////////////////////////////////////////////////////////////////////////////
//
#ifdef WIN32
#include <dbghelp.h>
typedef BOOL (__stdcall *tMDWD)(
IN HANDLE hProcess,
IN DWORD ProcessId,
IN HANDLE hFile,
IN MINIDUMP_TYPE DumpType,
IN CONST PMINIDUMP_EXCEPTION_INFORMATION ExceptionParam, OPTIONAL
IN CONST PMINIDUMP_USER_STREAM_INFORMATION UserStreamParam, OPTIONAL
IN CONST PMINIDUMP_CALLBACK_INFORMATION CallbackParam OPTIONAL
);
static tMDWD s_pMDWD;
static HMODULE s_hDbgHelpMod;
static MINIDUMP_TYPE s_dumpTyp = MiniDumpNormal; // MiniDumpWithDataSegs or MiniDumpWithFullMemory
static wchar_t s_szMiniDumpName[64];
static LONG __stdcall MyCrashHandlerExceptionFilter(EXCEPTION_POINTERS* pEx)
{
#ifdef _M_IX86
if (pEx->ExceptionRecord->ExceptionCode == EXCEPTION_STACK_OVERFLOW)
{
// be sure that we have enought space...
static char MyStack[1024*128];
// it assumes that DS and SS are the same!!! (this is the case for Win32)
// change the stack only if the selectors are the same (this is the case for Win32)
//__asm push offset MyStack[1024*128];
//__asm pop esp;
__asm mov eax,offset MyStack[1024*128];
__asm mov esp,eax;
}
#endif
bool bSuccess = false;
wchar_t szMiniDumpFileName[128];
wsprintf(szMiniDumpFileName, L"%s %s.dmp", s_szMiniDumpName, QDateTime::currentDateTime().toString("dd.MM.yyyy hh-mm-ss,zzz").replace(QRegExp("[:*?<>|\"\\/]"), "_").toStdWString().c_str());
wchar_t szMiniDumpPath[MAX_PATH] = { 0 };
HANDLE hFile = CreateFile(szMiniDumpFileName, GENERIC_WRITE, 0, NULL, CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL);
if (hFile != INVALID_HANDLE_VALUE)
GetCurrentDirectory(MAX_PATH, szMiniDumpPath);
else
{
GetTempPath(MAX_PATH, szMiniDumpPath);
wchar_t szMiniDumpFilePath[MAX_PATH] = { 0 };
wsprintf(szMiniDumpFilePath, L"%s\\%s.dmp", szMiniDumpPath, szMiniDumpFileName);
hFile = CreateFile(szMiniDumpFilePath, GENERIC_WRITE, 0, NULL, CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL);
}
if (hFile != INVALID_HANDLE_VALUE)
{
MINIDUMP_EXCEPTION_INFORMATION stMDEI;
stMDEI.ThreadId = GetCurrentThreadId();
stMDEI.ExceptionPointers = pEx;
stMDEI.ClientPointers = TRUE;
// try to create an miniDump:
if (s_pMDWD(GetCurrentProcess(), GetCurrentProcessId(), hFile, s_dumpTyp, &stMDEI, NULL, NULL))
{
bSuccess = true;
}
CloseHandle(hFile);
}
wchar_t szMiniDumpMessage[256];
if (!bSuccess)
wsprintf(szMiniDumpMessage, L"%s crashed!\r\nCrashdump creation failed.", s_szMiniDumpName);
else
wsprintf(szMiniDumpMessage, L"%s crashed!\r\nCrashdump saved to \"%s\".\r\nPlease report the crash and attach the file \"%s\".", s_szMiniDumpName, szMiniDumpPath, szMiniDumpFileName);
MessageBox(NULL, szMiniDumpMessage, s_szMiniDumpName, MB_OK | MB_ICONERROR);
// or return one of the following:
// - EXCEPTION_CONTINUE_SEARCH
// - EXCEPTION_CONTINUE_EXECUTION
// - EXCEPTION_EXECUTE_HANDLER
return EXCEPTION_CONTINUE_SEARCH; // this will trigger the "normal" OS error-dialog
}
void InitMiniDumpWriter(const wchar_t* Name)
{
if (s_hDbgHelpMod != NULL)
return;
ASSERT(wcslen(Name) < ARRSIZE(s_szMiniDumpName));
wcscpy(s_szMiniDumpName, Name);
// Initialize the member, so we do not load the dll after the exception has occured
// which might be not possible anymore...
s_hDbgHelpMod = LoadLibrary(L"dbghelp.dll");
if (s_hDbgHelpMod != NULL)
s_pMDWD = (tMDWD) GetProcAddress(s_hDbgHelpMod, "MiniDumpWriteDump");
// Register Unhandled Exception-Filter:
SetUnhandledExceptionFilter(MyCrashHandlerExceptionFilter);
// Additional call "PreventSetUnhandledExceptionFilter"...
// See also: "SetUnhandledExceptionFilter" and VC8 (and later)
// http://blog.kalmbachnet.de/?postid=75
}
quint64 GetCurCycle()
{
quint64 freq, now;
QueryPerformanceFrequency((LARGE_INTEGER*)&freq);
QueryPerformanceCounter((LARGE_INTEGER*)&now);
quint64 dwNow = ((now * 1000000) / freq) & 0xffffffff;
return dwNow; // returns time since system start in us
}
#elif !defined(__APPLE__)
#include <stdio.h>
#include <execinfo.h>
#include <signal.h>
#include <stdlib.h>
#include <unistd.h>
static wchar_t s_szMiniDumpName[64];
/* This structure mirrors the one found in /usr/include/asm/ucontext.h */
typedef struct _sig_ucontext {
unsigned long uc_flags;
struct ucontext *uc_link;
stack_t uc_stack;
struct sigcontext uc_mcontext;
sigset_t uc_sigmask;
} sig_ucontext_t;
void crit_err_hdlr(int sig_num, siginfo_t * info, void * ucontext)
{
void * array[50];
void * caller_address;
char ** messages;
int size, i;
sig_ucontext_t * uc;
uc = (sig_ucontext_t *)ucontext;
/* Get the address at the time the signal was raised */
#if defined(__i386__) // gcc specific
caller_address = (void *) uc->uc_mcontext.eip; // EIP: x86 specific
#elif defined(__x86_64__) // gcc specific
caller_address = (void *) uc->uc_mcontext.rip; // RIP: x86_64 specific
#else
#error Unsupported architecture. // TO-DO: Add support for other arch.
#endif
fprintf(stderr, "signal %d (%s), address is %p from %p\n",
sig_num, strsignal(sig_num), info->si_addr,
(void *)caller_address);
size = backtrace(array, 50);
/* overwrite sigaction with caller's address */
array[1] = caller_address;
messages = backtrace_symbols(array, size);
char szMiniDumpFileName[128];
sprintf(szMiniDumpFileName, "%S_%s.log", s_szMiniDumpName, QDateTime::currentDateTime().toString("dd.MM.yyyy_hh-mm-ss,zzz").replace(QRegExp("[:*?<>|\"\\/]"), "_").toStdString().c_str());
FILE* file = fopen(szMiniDumpFileName, "wb");
/* skip first stack frame (points here) */
for (i = 1; i < size && messages != NULL; ++i)
{
fprintf(stderr, "[bt]: (%d) %s\n", i, messages[i]);
fprintf(file, "[bt]: (%d) %s\n", i, messages[i]);
}
fclose(file);
free(messages);
exit(EXIT_FAILURE);
}
void InstallSigAction(int sig)
{
struct sigaction sigact;
sigact.sa_sigaction = crit_err_hdlr;
sigact.sa_flags = SA_RESTART | SA_SIGINFO;
if (sigaction(sig, &sigact, (struct sigaction *)NULL) != 0)
{
fprintf(stderr, "error setting signal handler for %d (%s)\n", sig, strsignal(sig));
exit(EXIT_FAILURE);
}
}
void InitMiniDumpWriter(const wchar_t* Name)
{
ASSERT(wcslen(Name) < ARRSIZE(s_szMiniDumpName));
wcscpy(s_szMiniDumpName, Name);
InstallSigAction(SIGABRT);
InstallSigAction(SIGSEGV);
}
quint64 GetCurCycle()
{
return GetCurTick()*1000; // ToDo
}
#else
void InitMiniDumpWriter(const wchar_t* Name)
{
}
#endif

View File

@ -0,0 +1,173 @@
#pragma once
//#define _TRACE
#include "../mischelpers_global.h"
MISCHELPERS_EXPORT bool IsDebuggerAttached();
MISCHELPERS_EXPORT void WaitForDebugger();
#if defined(_DEBUG) || defined(_TRACE)
MISCHELPERS_EXPORT void Assert(bool test);
#define TRACE CTracer()
#define ASSERT(x) Assert(x)
#define VERIFY(f) ASSERT(f)
#define DEBUG_ONLY(f) (f)
MISCHELPERS_EXPORT extern bool g_assert_active;
class MISCHELPERS_EXPORT CTracer
{
public:
void operator()(const QString &sLine) const;
void operator()(const wchar_t *sLine, ...) const;
void operator()(const char *sLine, ...) const;
};
////////////////////////////////////////////////////////////////////////////////////////////
// Tracers
////////////////////////////////////////////////////////////////////////////////////////////
class MISCHELPERS_EXPORT CMemTracer
{
public:
//CMemTracer();
//~CMemTracer();
void DumpTrace();
void TraceAlloc(string Name);
void TraceFree(string Name);
void TracePre(string Name);
private:
QMutex m_Locker;
map<string,int> m_MemoryTrace;
map<string,int> m_MemoryTrace2;
};
MISCHELPERS_EXPORT extern CMemTracer memTracer;
#define TRACE_ALLOC(x) memTracer.TraceAlloc(x);
#define TRACE_FREE(x) memTracer.TraceFree(x);
#define TRACE_PRE_FREE(x) memTracer.TracePre(x);
#define TRACE_MEMORY memTracer.DumpTrace();
class MISCHELPERS_EXPORT CCpuTracer
{
public:
//CCpuTracer();
//~CCpuTracer();
void DumpTrace();
void ResetTrace();
void TraceStart(string Name);
void TraceStop(string Name);
private:
struct SCycles
{
SCycles()
{
Counting = 0;
Total = 0;
}
quint64 Counting;
quint64 Total;
};
QMutex m_Locker;
map<string,SCycles> m_CpuUsageTrace;
};
MISCHELPERS_EXPORT extern CCpuTracer cpuTracer;
#define TRACE_RESET cpuTracer.ResetTrace();
#define TRACE_START(x) cpuTracer.TraceStart(x);
#define TRACE_STOP(x) cpuTracer.TraceStop(x);
#define TRACE_CPU cpuTracer.DumpTrace();
class MISCHELPERS_EXPORT CLockTracer
{
public:
//CLockTracer();
//~CLockTracer();
void DumpTrace();
void TraceLock(string Name, int op);
private:
QMutex m_Locker;
struct SLocks
{
SLocks()
{
LockTime = 0;
LockCount = 0;
}
time_t LockTime;
int LockCount;
};
map<string,SLocks> m_LockTrace;
};
MISCHELPERS_EXPORT extern CLockTracer lockTracer;
#define TRACE_LOCK(x) lockTracer.TraceLock(x,1);
#define TRACE_UNLOCK(x)lockTracer.TraceLock(x,-1);
#define TRACE_LOCKING lockTracer.DumpTrace();
class MISCHELPERS_EXPORT CLockerTrace
{
public:
CLockerTrace(string Name)
{
m_Name = Name;
lockTracer.TraceLock(m_Name,1);
}
~CLockerTrace()
{
lockTracer.TraceLock(m_Name,-1);
}
private:
string m_Name;
};
#define TRACE_LOCKER(x)CLockerTrace LockTrace(x)
#else
//#define X_ASSERT(x) if(!(x)) throw "Assertion failed in: " __FUNCTION__ "; File:" __FILE__ "; Line:" STR(__LINE__) ";";
#define TRACE
#define ASSERT(x)
#define VERIFY(f) (f)
#define DEBUG_ONLY(f)
#define TRACE_ALLOC(x)
#define TRACE_FREE(x)
#define TRACE_MEMORY
#define TRACE_RESET
#define TRACE_START(x)
#define TRACE_STOP(x)
#define TRACE_CPUUSAGE
#define TRACE_CPU
#define TRACE_LOCK(x)
#define TRACE_UNLOCK(x)
#define TRACE_LOCKING
#define TRACE_LOCKER(x)
#endif
MISCHELPERS_EXPORT void InitMiniDumpWriter(const wchar_t* Name);
MISCHELPERS_EXPORT quint64 GetCurCycle();

View File

@ -0,0 +1,66 @@
#pragma once
#include "../mischelpers_global.h"
class MISCHELPERS_EXPORT CExitDialog : public QDialog
{
public:
CExitDialog(const QString& Prompt, QWidget* parent = 0)
: QDialog(parent)
{
m_pMainLayout = new QGridLayout(this);
QLabel* pLabel = new QLabel(Prompt);
m_pMainLayout->addWidget(pLabel, 0, 0, 1, 1);
m_pButtonBox = new QDialogButtonBox();
m_pButtonBox->setOrientation(Qt::Horizontal);
m_pButtonBox->setStandardButtons(QDialogButtonBox::Yes|QDialogButtonBox::No);
m_pMainLayout->addWidget(m_pButtonBox, 2, 0, 1, 1);
connect(m_pButtonBox,SIGNAL(accepted()),this,SLOT(accept()));
connect(m_pButtonBox,SIGNAL(rejected()),this,SLOT(reject()));
m_TimerId = startTimer(1000);
m_CountDown = 15;
}
~CExitDialog()
{
killTimer(m_TimerId);
}
protected:
void timerEvent(QTimerEvent *e)
{
if (e->timerId() != m_TimerId)
{
QDialog::timerEvent(e);
return;
}
if(m_CountDown != 0)
{
m_CountDown--;
m_pButtonBox->button(QDialogButtonBox::Yes)->setText(tr("Yes (%1)").arg(m_CountDown));
if(m_CountDown == 0)
accept();
}
}
void reject()
{
hide();
}
void closeEvent(QCloseEvent *e)
{
hide();
e->ignore();
}
int m_TimerId;
int m_CountDown;
QGridLayout* m_pMainLayout;
QDialogButtonBox * m_pButtonBox;
};

View File

@ -0,0 +1,125 @@
#include "stdafx.h"
#include "Finder.h"
QWidget* CFinder::AddFinder(QWidget* pList, QObject* pFilterTarget, bool HighLightOption, CFinder** ppFinder)
{
QWidget* pWidget = new QWidget();
QVBoxLayout* pLayout = new QVBoxLayout();
pLayout->setMargin(0);
pWidget->setLayout(pLayout);
pLayout->addWidget(pList);
CFinder* pFinder = new CFinder(pFilterTarget, pWidget, HighLightOption);
pLayout->addWidget(pFinder);
if (ppFinder)
*ppFinder = pFinder;
return pWidget;
}
CFinder::CFinder(QObject* pFilterTarget, QWidget *parent, bool HighLightOption)
:QWidget(parent)
{
m_pSearchLayout = new QHBoxLayout();
m_pSearchLayout->setMargin(3);
m_pSearchLayout->setSpacing(3);
m_pSearchLayout->setAlignment(Qt::AlignLeft);
m_pSearch = new QLineEdit();
m_pSearch->setMinimumWidth(150);
m_pSearch->setMaximumWidth(350);
m_pSearchLayout->addWidget(m_pSearch);
QObject::connect(m_pSearch, SIGNAL(textChanged(QString)), this, SLOT(OnUpdate()));
//QObject::connect(m_pSearch, SIGNAL(returnPressed()), this, SLOT(_q_next()));
m_pCaseSensitive = new QCheckBox(tr("Case Sensitive"));
m_pSearchLayout->addWidget(m_pCaseSensitive);
connect(m_pCaseSensitive, SIGNAL(stateChanged(int)), this, SLOT(OnUpdate()));
m_pRegExp = new QCheckBox(tr("RegExp"));
m_pSearchLayout->addWidget(m_pRegExp);
connect(m_pRegExp, SIGNAL(stateChanged(int)), this, SLOT(OnUpdate()));
m_pColumn = new QComboBox();
m_pSearchLayout->addWidget(m_pColumn);
connect(m_pColumn, SIGNAL(currentIndexChanged(int)), this, SLOT(OnUpdate()));
m_pColumn->setVisible(false);
if (HighLightOption)
{
m_pHighLight = new QCheckBox(tr("Highlight"));
m_pSearchLayout->addWidget(m_pHighLight);
connect(m_pHighLight, SIGNAL(stateChanged(int)), this, SLOT(OnUpdate()));
}
else
m_pHighLight = NULL;
QToolButton* pClose = new QToolButton(this);
pClose->setIcon(QIcon(":/close.png"));
pClose->setAutoRaise(true);
pClose->setText(tr("Close"));
m_pSearchLayout->addWidget(pClose);
QObject::connect(pClose, SIGNAL(clicked()), this, SLOT(Close()));
QWidget* pSpacer = new QWidget();
pSpacer->setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Expanding);
m_pSearchLayout->addWidget(pSpacer);
setLayout(m_pSearchLayout);
setMaximumHeight(30);
hide();
if (parent)
{
QAction* pFind = new QAction(tr("&Find ..."), parent);
pFind->setShortcut(QKeySequence::Find);
pFind->setShortcutContext(Qt::WidgetWithChildrenShortcut);
parent->addAction(pFind);
QObject::connect(pFind, SIGNAL(triggered()), this, SLOT(Open()));
}
m_pSortProxy = qobject_cast<QSortFilterProxyModel*>(pFilterTarget);
if (pFilterTarget)
QObject::connect(this, SIGNAL(SetFilter(const QRegExp&, bool, int)), pFilterTarget, SLOT(SetFilter(const QRegExp&, bool, int)));
}
CFinder::~CFinder()
{
}
void CFinder::Open()
{
if (m_pSortProxy && m_pColumn->count() == 0)
{
m_pColumn->addItem(tr("All columns"), -1);
for (int i = 0; i < m_pSortProxy->columnCount(); i++)
m_pColumn->addItem(m_pSortProxy->headerData(i, Qt::Horizontal, Qt::DisplayRole).toString(), i);
m_pColumn->setVisible(true);
}
show();
m_pSearch->setFocus(Qt::OtherFocusReason);
m_pSearch->selectAll();
OnUpdate();
}
QRegExp CFinder::GetRegExp() const
{
if (!isVisible())
return QRegExp();
return QRegExp(m_pSearch->text(), m_pCaseSensitive->isChecked() ? Qt::CaseSensitive : Qt::CaseInsensitive, m_pRegExp->isChecked() ? QRegExp::RegExp : QRegExp::FixedString);
}
void CFinder::OnUpdate()
{
emit SetFilter(GetRegExp(), GetHighLight(), GetColumn());
}
void CFinder::Close()
{
emit SetFilter(QRegExp());
hide();
}

View File

@ -0,0 +1,38 @@
#pragma once
#include "../mischelpers_global.h"
class MISCHELPERS_EXPORT CFinder: public QWidget
{
Q_OBJECT
public:
CFinder(QObject* pFilterTarget, QWidget *parent = NULL, bool HighLightOption = true);
~CFinder();
static QWidget* AddFinder(QWidget* pList, QObject* pFilterTarget, bool HighLightOption = true, CFinder** ppFinder = NULL);
QRegExp GetRegExp() const;
bool GetHighLight() const { return m_pHighLight ? m_pHighLight->isChecked() : false; }
int GetColumn() const { return m_pColumn->currentData().toInt(); }
signals:
void SetFilter(const QRegExp& Exp, bool bHighLight = false, int Column = -1);
public slots:
void Open();
void OnUpdate();
void Close();
private:
QHBoxLayout* m_pSearchLayout;
QLineEdit* m_pSearch;
QCheckBox* m_pCaseSensitive;
QCheckBox* m_pRegExp;
QComboBox* m_pColumn;
QCheckBox* m_pHighLight;
QSortFilterProxyModel* m_pSortProxy;
};

View File

@ -0,0 +1,87 @@
#pragma once
#define ERROR_UNDEFINED (1)
#define ERROR_CONFIRM (2)
#define ERROR_INTERNAL (3)
#define ERROR_PARAMS (4)
#include "../mischelpers_global.h"
class MISCHELPERS_EXPORT CFlexError
{
public:
CFlexError()
{
m = NULL;
}
CFlexError(const QString& Error, long Status = ERROR_UNDEFINED) : CFlexError()
{
Attach(MkError(Error, Status));
}
CFlexError(long Status) : CFlexError(QObject::tr("Error"), Status)
{
}
CFlexError(const CFlexError& other) : CFlexError()
{
if(other.m != NULL)
Attach((SFlexError*)other.m);
}
~CFlexError()
{
Detach();
}
CFlexError& operator=(const CFlexError& Array)
{
Attach(Array.m);
return *this;
}
__inline bool IsError() const { return m != NULL; }
__inline long GetStatus() const { return m ? m->Status : 0; }
__inline QString GetText() const { return m ? m->Error: ""; }
operator bool() const {return !IsError();}
private:
struct SFlexError
{
QString Error;
long Status;
mutable atomic<int> aRefCnt;
} *m;
SFlexError* MkError(const QString& Error, long Status)
{
SFlexError* p = new SFlexError();
p->Error = Error;
p->Status = Status;
return p;
}
void Attach(SFlexError* p)
{
Detach();
if (p != NULL)
{
p->aRefCnt.fetch_add(1);
m = p;
}
}
void Detach()
{
if (m != NULL)
{
if (m->aRefCnt.fetch_sub(1) == 1)
delete m;
m = NULL;
}
}
};
typedef CFlexError STATUS;
#define OK CFlexError()
#define ERR CFlexError

View File

@ -0,0 +1,223 @@
/****************************************************************************
**
** Copyright (C) 2016 The Qt Company Ltd.
** Contact: https://www.qt.io/licensing/
**
** This file is part of the examples of the Qt Toolkit.
**
** $QT_BEGIN_LICENSE:BSD$
** Commercial License Usage
** Licensees holding valid commercial Qt licenses may use this file in
** accordance with the commercial license agreement provided with the
** Software or, alternatively, in accordance with the terms contained in
** a written agreement between you and The Qt Company. For licensing terms
** and conditions see https://www.qt.io/terms-conditions. For further
** information use the contact form at https://www.qt.io/contact-us.
**
** BSD License Usage
** Alternatively, you may use this file under the terms of the BSD license
** as follows:
**
** "Redistribution and use in source and binary forms, with or without
** modification, are permitted provided that the following conditions are
** met:
** * Redistributions of source code must retain the above copyright
** notice, this list of conditions and the following disclaimer.
** * Redistributions in binary form must reproduce the above copyright
** notice, this list of conditions and the following disclaimer in
** the documentation and/or other materials provided with the
** distribution.
** * Neither the name of The Qt Company Ltd nor the names of its
** contributors may be used to endorse or promote products derived
** from this software without specific prior written permission.
**
**
** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE."
**
** $QT_END_LICENSE$
**
****************************************************************************/
#include "stdafx.h"
#include "FlowLayout.h"
//! [1]
QFlowLayout::QFlowLayout(QWidget *parent, int margin, int hSpacing, int vSpacing)
: QLayout(parent), m_hSpace(hSpacing), m_vSpace(vSpacing)
{
setContentsMargins(margin, margin, margin, margin);
}
QFlowLayout::QFlowLayout(int margin, int hSpacing, int vSpacing)
: m_hSpace(hSpacing), m_vSpace(vSpacing)
{
setContentsMargins(margin, margin, margin, margin);
}
//! [1]
//! [2]
QFlowLayout::~QFlowLayout()
{
QLayoutItem *item;
while ((item = takeAt(0)))
delete item;
}
//! [2]
//! [3]
void QFlowLayout::addItem(QLayoutItem *item)
{
itemList.append(item);
}
//! [3]
//! [4]
int QFlowLayout::horizontalSpacing() const
{
if (m_hSpace >= 0) {
return m_hSpace;
} else {
return smartSpacing(QStyle::PM_LayoutHorizontalSpacing);
}
}
int QFlowLayout::verticalSpacing() const
{
if (m_vSpace >= 0) {
return m_vSpace;
} else {
return smartSpacing(QStyle::PM_LayoutVerticalSpacing);
}
}
//! [4]
//! [5]
int QFlowLayout::count() const
{
return itemList.size();
}
QLayoutItem *QFlowLayout::itemAt(int index) const
{
return itemList.value(index);
}
QLayoutItem *QFlowLayout::takeAt(int index)
{
if (index >= 0 && index < itemList.size())
return itemList.takeAt(index);
else
return 0;
}
//! [5]
//! [6]
Qt::Orientations QFlowLayout::expandingDirections() const
{
return 0;
}
//! [6]
//! [7]
bool QFlowLayout::hasHeightForWidth() const
{
return true;
}
int QFlowLayout::heightForWidth(int width) const
{
int height = doLayout(QRect(0, 0, width, 0), true);
return height;
}
//! [7]
//! [8]
void QFlowLayout::setGeometry(const QRect &rect)
{
QLayout::setGeometry(rect);
doLayout(rect, false);
}
QSize QFlowLayout::sizeHint() const
{
return minimumSize();
}
QSize QFlowLayout::minimumSize() const
{
QSize size;
QLayoutItem *item;
foreach (item, itemList)
size = size.expandedTo(item->minimumSize());
size += QSize(2*margin(), 2*margin());
return size;
}
//! [8]
//! [9]
int QFlowLayout::doLayout(const QRect &rect, bool testOnly) const
{
int left, top, right, bottom;
getContentsMargins(&left, &top, &right, &bottom);
QRect effectiveRect = rect.adjusted(+left, +top, -right, -bottom);
int x = effectiveRect.x();
int y = effectiveRect.y();
int lineHeight = 0;
//! [9]
//! [10]
QLayoutItem *item;
foreach (item, itemList) {
QWidget *wid = item->widget();
int spaceX = horizontalSpacing();
if (spaceX == -1)
spaceX = wid->style()->layoutSpacing(
QSizePolicy::PushButton, QSizePolicy::PushButton, Qt::Horizontal);
int spaceY = verticalSpacing();
if (spaceY == -1)
spaceY = wid->style()->layoutSpacing(
QSizePolicy::PushButton, QSizePolicy::PushButton, Qt::Vertical);
//! [10]
//! [11]
int nextX = x + item->sizeHint().width() + spaceX;
if (nextX - spaceX > effectiveRect.right() && lineHeight > 0) {
x = effectiveRect.x();
y = y + lineHeight + spaceY;
nextX = x + item->sizeHint().width() + spaceX;
lineHeight = 0;
}
if (!testOnly)
item->setGeometry(QRect(QPoint(x, y), item->sizeHint()));
x = nextX;
lineHeight = qMax(lineHeight, item->sizeHint().height());
}
return y + lineHeight - rect.y() + bottom;
}
//! [11]
//! [12]
int QFlowLayout::smartSpacing(QStyle::PixelMetric pm) const
{
QObject *parent = this->parent();
if (!parent) {
return -1;
} else if (parent->isWidgetType()) {
QWidget *pw = static_cast<QWidget *>(parent);
return pw->style()->pixelMetric(pm, 0, pw);
} else {
return static_cast<QLayout *>(parent)->spacing();
}
}
//! [12]

View File

@ -0,0 +1,90 @@
/****************************************************************************
**
** Copyright (C) 2016 The Qt Company Ltd.
** Contact: https://www.qt.io/licensing/
**
** This file is part of the examples of the Qt Toolkit.
**
** $QT_BEGIN_LICENSE:BSD$
** Commercial License Usage
** Licensees holding valid commercial Qt licenses may use this file in
** accordance with the commercial license agreement provided with the
** Software or, alternatively, in accordance with the terms contained in
** a written agreement between you and The Qt Company. For licensing terms
** and conditions see https://www.qt.io/terms-conditions. For further
** information use the contact form at https://www.qt.io/contact-us.
**
** BSD License Usage
** Alternatively, you may use this file under the terms of the BSD license
** as follows:
**
** "Redistribution and use in source and binary forms, with or without
** modification, are permitted provided that the following conditions are
** met:
** * Redistributions of source code must retain the above copyright
** notice, this list of conditions and the following disclaimer.
** * Redistributions in binary form must reproduce the above copyright
** notice, this list of conditions and the following disclaimer in
** the documentation and/or other materials provided with the
** distribution.
** * Neither the name of The Qt Company Ltd nor the names of its
** contributors may be used to endorse or promote products derived
** from this software without specific prior written permission.
**
**
** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE."
**
** $QT_END_LICENSE$
**
****************************************************************************/
#ifndef QFlowLayout_H
#define QFlowLayout_H
#include <QLayout>
#include <QRect>
#include <QStyle>
//! [0]
#include "../mischelpers_global.h"
class MISCHELPERS_EXPORT QFlowLayout : public QLayout
{
public:
explicit QFlowLayout(QWidget *parent, int margin = -1, int hSpacing = -1, int vSpacing = -1);
explicit QFlowLayout(int margin = -1, int hSpacing = -1, int vSpacing = -1);
~QFlowLayout();
void addItem(QLayoutItem *item) override;
int horizontalSpacing() const;
int verticalSpacing() const;
Qt::Orientations expandingDirections() const override;
bool hasHeightForWidth() const override;
int heightForWidth(int) const override;
int count() const override;
QLayoutItem *itemAt(int index) const override;
QSize minimumSize() const override;
void setGeometry(const QRect &rect) override;
QSize sizeHint() const override;
QLayoutItem *takeAt(int index) override;
private:
int doLayout(const QRect &rect, bool testOnly) const;
int smartSpacing(QStyle::PixelMetric pm) const;
QList<QLayoutItem *> itemList;
int m_hSpace;
int m_vSpace;
};
//! [0]
#endif // QFlowLayout_H

View File

@ -0,0 +1,161 @@
#pragma once
#include "../mischelpers_global.h"
class MISCHELPERS_EXPORT CHistoryGraph: public QObject
{
public:
CHistoryGraph(bool bSimpleMode = false, QColor BkG = Qt::white, QObject* parent = NULL) : QObject(parent) {
m_SimpleMode = bSimpleMode;
m_BkG = BkG;
}
~CHistoryGraph() {}
void AddValue(int Id, QColor Color)
{
m_Values.insert(Id, { 0.0, Color });
}
void SetValue(int Id, float Value)
{
m_Values[Id].Value = Value;
}
void Update(int CellHeight, int CellWidth)
{
Update(m_Graph, m_BkG, m_Values, CellHeight, CellWidth, m_SimpleMode);
}
QImage GetImage() const { return m_Graph; }
struct SValue
{
float Value;
QColor Color;
};
static void Update(QImage& m_Graph, const QColor& m_BkG, const QMap<int, SValue>& m_Values, int CellHeight, int CellWidth, bool m_SimpleMode = true)
{
// init / resize
if(m_Graph.height() != CellWidth /*|| m_Graph.width() != curHeight*/)
{
QImage Graph = QImage(CellHeight, CellWidth, QImage::Format_RGB32);
QPainter qp(&Graph);
qp.fillRect(-1, -1, CellHeight+1, CellWidth+1, m_BkG);
if (!m_Graph.isNull())
qp.drawImage(0, Graph.height() - m_Graph.height(), m_Graph);
m_Graph = Graph;
}
// shift
uchar *dest = m_Graph.bits();
int pos = m_Graph.sizeInBytes() - m_Graph.bytesPerLine();
memmove(dest, dest + m_Graph.bytesPerLine(), pos);
QPainter qp(&m_Graph);
// draw new data points
int top = 0;
#if 0
foreach(const SValue& Value, m_Values)
{
int x = (float)(m_Graph.width()) * Value.Value;
if (x > top)
top = x;
qp.setPen(Value.Color);
qp.drawLine(0, m_Graph.height() - 1, x, m_Graph.height());
}
qp.setPen(Qt::white);
qp.drawLine(top, m_Graph.height() - 1, m_Graph.width()-1, m_Graph.height());
#else
dest += pos;
memset(dest, 0, m_Graph.bytesPerLine()); // fill line black
ASSERT(m_Graph.depth() == 32);
int max = m_Graph.width();
//ASSERT(max * 4 == m_Graph.bytesPerLine());
foreach(const SValue& Value, m_Values)
{
int x = (float)(max) * Value.Value;
if (x > max)
x = max;
if (x > top)
top = x;
x *= 4;
int r, g, b;
Value.Color.getRgb(&r, &g, &b);
for (int i = 0; i < x; i += 4)
{
if (m_SimpleMode || *(quint32*)(dest + i) == 0)
{
dest[i ] = b;
dest[i + 1] = g;
dest[i + 2] = r;
}
else
{
#define DIV 4/5
int cb = (int)dest[i ]*DIV + b*DIV;
int cg = (int)dest[i + 1]*DIV + g*DIV;
int cr = (int)dest[i + 2]*DIV + r*DIV;
dest[i ] = qMin(cb, 255);
dest[i + 1] = qMin(cg, 255);
dest[i + 2] = qMin(cr, 255);
}
}
}
// fill whats left of the line
/*top *= 4;
if (top < m_Graph.bytesPerLine()) // fill rest white
memset(dest + top, 0xFF, m_Graph.bytesPerLine() - top);*/
{
int r, g, b;
m_BkG.getRgb(&r, &g, &b);
top *= 4;
max *= 4;
for (int i = top; i < max; i += 4)
{
dest[i] = b;
dest[i + 1] = g;
dest[i + 2] = r;
}
}
#endif
}
protected:
QImage m_Graph;
QColor m_BkG;
QMap<int, SValue> m_Values;
bool m_SimpleMode;
};
class CHistoryWidget: public QWidget
{
public:
CHistoryWidget(CHistoryGraph* pHistoryGraph, QWidget* parent = NULL) : QWidget(parent) { m_pHistoryGraph = pHistoryGraph; }
~CHistoryWidget() {}
protected:
void paintEvent(QPaintEvent* e)
{
if (m_pHistoryGraph)
{
QImage HistoryGraph = m_pHistoryGraph->GetImage();
QPainter qp(this);
qp.translate(width() - HistoryGraph.height() - 1, height());
qp.rotate(270);
qp.drawImage(0, 0, HistoryGraph);
}
}
QPointer<CHistoryGraph> m_pHistoryGraph;
};

View File

@ -0,0 +1,307 @@
/****************************************************************************
**
** Copyright (C) 2016 The Qt Company Ltd.
** Contact: https://www.qt.io/licensing/
**
** This file is part of the QtWinExtras module of the Qt Toolkit.
**
** $QT_BEGIN_LICENSE:BSD$
** Commercial License Usage
** Licensees holding valid commercial Qt licenses may use this file in
** accordance with the commercial license agreement provided with the
** Software or, alternatively, in accordance with the terms contained in
** a written agreement between you and The Qt Company. For licensing terms
** and conditions see https://www.qt.io/terms-conditions. For further
** information use the contact form at https://www.qt.io/contact-us.
**
** BSD License Usage
** Alternatively, you may use this file under the terms of the BSD license
** as follows:
**
** "Redistribution and use in source and binary forms, with or without
** modification, are permitted provided that the following conditions are
** met:
** * Redistributions of source code must retain the above copyright
** notice, this list of conditions and the following disclaimer.
** * Redistributions in binary form must reproduce the above copyright
** notice, this list of conditions and the following disclaimer in
** the documentation and/or other materials provided with the
** distribution.
** * Neither the name of The Qt Company Ltd nor the names of its
** contributors may be used to endorse or promote products derived
** from this software without specific prior written permission.
**
**
** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE."
**
** $QT_END_LICENSE$
**
****************************************************************************/
#include "stdafx.h"
#include "IconExtreactor.h"
#include <QtWin>
//#include <iostream>
#include <shellapi.h>
#include <comdef.h>
#include <commctrl.h>
#include <objbase.h>
#include <commoncontrols.h>
/* This example demonstrates the Windows-specific image conversion
* functions. */
/*struct PixmapEntry {
QString name;
QPixmap pixmap;
};
typedef QVector<PixmapEntry> PixmapEntryList;*/
/*std::wostream &operator<<(std::wostream &str, const QString &s)
{
#ifdef Q_OS_WIN
str << reinterpret_cast<const wchar_t *>(s.utf16());
#else
str << s.toStdWString();
#endif
return str;
}*/
QString formatSize(const QSize &size)
{
return QString::number(size.width()) + u'x' + QString::number(size.height());
}
// Extract icons contained in executable or DLL using the Win32 API ExtractIconEx()
PixmapEntryList extractIcons(const QString &sourceFile, bool large)
{
const QString nativeName = QDir::toNativeSeparators(sourceFile);
const auto *sourceFileC = reinterpret_cast<const wchar_t *>(nativeName.utf16());
const UINT iconCount = ExtractIconEx(sourceFileC, -1, nullptr, nullptr, 0);
if (!iconCount) {
//std::wcerr << sourceFile << " does not appear to contain icons.\n";
return PixmapEntryList();
}
QScopedArrayPointer<HICON> icons(new HICON[iconCount]);
const UINT extractedIconCount = large ?
ExtractIconEx(sourceFileC, 0, icons.data(), nullptr, iconCount) :
ExtractIconEx(sourceFileC, 0, nullptr, icons.data(), iconCount);
if (!extractedIconCount) {
qErrnoWarning("Failed to extract icons from %s", qPrintable(sourceFile));
return PixmapEntryList();
}
PixmapEntryList result;
result.reserve(int(extractedIconCount));
//std::wcout << sourceFile << " contains " << extractedIconCount << " icon(s).\n";
for (UINT i = 0; i < extractedIconCount; ++i) {
PixmapEntry entry;
entry.pixmap = QtWin::fromHICON(icons[i]);
if (entry.pixmap.isNull()) {
//std::wcerr << "Error converting icons.\n";
return PixmapEntryList();
}
entry.name = QString::fromLatin1("%1_%2x%3").arg(i, 3, 10, QLatin1Char('0'))
.arg(entry.pixmap.width()).arg(entry.pixmap.height());
result.append(entry);
}
return result;
}
// Helper for extracting large/jumbo icons available from Windows Vista onwards
// via SHGetImageList().
QPixmap pixmapFromShellImageList(int iImageList, const SHFILEINFO &info)
{
QPixmap result;
// For MinGW:
const IID iID_IImageList = { 0x46eb5926, 0x582e, 0x4017, {0x9f, 0xdf, 0xe8, 0x99, 0x8d, 0xaa, 0x9, 0x50} };
IImageList *imageList = nullptr;
if (FAILED(SHGetImageList(iImageList, iID_IImageList, reinterpret_cast<void **>(&imageList))))
return result;
HICON hIcon = nullptr;
if (SUCCEEDED(imageList->GetIcon(info.iIcon, ILD_TRANSPARENT, &hIcon))) {
result = QtWin::fromHICON(hIcon);
DestroyIcon(hIcon);
}
return result;
}
// Extract icons that would be displayed by the Explorer (shell)
PixmapEntryList extractShellIcons(const QString &sourceFile, bool addOverlays)
{
enum { // Shell image list ids
sHIL_EXTRALARGE = 0x2, // 48x48 or user-defined
sHIL_JUMBO = 0x4 // 256x256 (Vista or later)
};
struct FlagEntry {
const char *name;
unsigned flags;
};
const FlagEntry modeEntries[] =
{
{"", 0},
{"open", SHGFI_OPENICON},
{"sel", SHGFI_SELECTED},
};
const FlagEntry standardSizeEntries[] =
{
{"s", SHGFI_SMALLICON},
{"l", SHGFI_LARGEICON},
{"sh", SHGFI_SHELLICONSIZE},
};
const QString nativeName = QDir::toNativeSeparators(sourceFile);
const auto *sourceFileC = reinterpret_cast<const wchar_t *>(nativeName.utf16());
SHFILEINFO info;
unsigned int baseFlags = SHGFI_ICON | SHGFI_SYSICONINDEX | SHGFI_ICONLOCATION;
if (addOverlays)
baseFlags |= SHGFI_ADDOVERLAYS | SHGFI_OVERLAYINDEX;
if (!QFileInfo(sourceFile).isDir())
baseFlags |= SHGFI_USEFILEATTRIBUTES;
PixmapEntryList result;
for (auto modeEntry : modeEntries) {
const unsigned modeFlags = baseFlags | modeEntry.flags;
QString modePrefix = QLatin1String("_shell_");
if (modeEntry.name[0])
modePrefix += QLatin1String(modeEntry.name) + u'_';
for (auto standardSizeEntry : standardSizeEntries) {
const unsigned flags = modeFlags | standardSizeEntry.flags;
const QString prefix = modePrefix + QLatin1String(standardSizeEntry.name)
+ u'_';
ZeroMemory(&info, sizeof(SHFILEINFO));
const HRESULT hr = SHGetFileInfo(sourceFileC, 0, &info, sizeof(SHFILEINFO), flags);
if (FAILED(hr)) {
_com_error error(hr);
//std::wcerr << "SHGetFileInfo() failed for \"" << nativeName << "\", "
// << std::hex << std::showbase << flags << std::dec << std::noshowbase
// << " (" << prefix << "): " << error.ErrorMessage() << '\n';
continue;
}
if (info.hIcon) {
PixmapEntry entry;
entry.pixmap = QtWin::fromHICON(info.hIcon);
DestroyIcon(info.hIcon);
if (entry.pixmap.isNull()) {
//std::wcerr << "Error converting icons.\n";
return PixmapEntryList();
}
entry.name = prefix + formatSize(entry.pixmap.size());
const int iconIndex = info.iIcon & 0xFFFFFF;
const int overlayIconIndex = info.iIcon >> 24;
//std::wcout << "Obtained icon #" << iconIndex;
//if (addOverlays)
// std::wcout << " (overlay #" << overlayIconIndex << ')';
//if (info.szDisplayName[0])
// std::wcout << " from " << QString::fromWCharArray(info.szDisplayName);
//std::wcout << " (" << entry.pixmap.width() << 'x'
// << entry.pixmap.height() << ") for " << std::hex << std::showbase << flags
// << std::dec << std::noshowbase << '\n';
result.append(entry);
}
} // for standardSizeEntryCount
// Windows Vista onwards: extract large/jumbo icons
if (info.hIcon) {
const QPixmap extraLarge = pixmapFromShellImageList(sHIL_EXTRALARGE, info);
if (!extraLarge.isNull()) {
PixmapEntry entry;
entry.pixmap = extraLarge;
entry.name = modePrefix + QLatin1String("xl_") + formatSize(extraLarge.size());
result.append(entry);
}
const QPixmap jumbo = pixmapFromShellImageList(sHIL_JUMBO, info);
if (!jumbo.isNull()) {
PixmapEntry entry;
entry.pixmap = jumbo;
entry.name = modePrefix + QLatin1String("jumbo_") + formatSize(extraLarge.size());
result.append(entry);
}
}
} // for modes
return result;
}
/*
const char description[] =
"\nExtracts Windows icons from executables, DLL or icon files and writes them\n"
"out as numbered .png-files.\n"
"When passing the --shell option, the icons displayed by Explorer are extracted.\n";
#include <QCommandLineParser>
#include <QCommandLineOption>
int main(int argc, char *argv[])
{
QGuiApplication app(argc, argv);
QCoreApplication::setApplicationName(QStringLiteral("Icon Extractor"));
QCoreApplication::setOrganizationName(QStringLiteral("QtProject"));
QCoreApplication::setApplicationVersion(QLatin1String(QT_VERSION_STR));
QCommandLineParser parser;
parser.setSingleDashWordOptionMode(QCommandLineParser::ParseAsCompactedShortOptions);
parser.setApplicationDescription(QLatin1String(description));
parser.addHelpOption();
parser.addVersionOption();
const QCommandLineOption largeIconOption(QStringLiteral("large"), QStringLiteral("Extract large icons"));
parser.addOption(largeIconOption);
const QCommandLineOption shellIconOption(QStringLiteral("shell"), QStringLiteral("Extract shell icons using SHGetFileInfo()"));
parser.addOption(shellIconOption);
const QCommandLineOption shellOverlayOption(QStringLiteral("overlay"), QStringLiteral("Extract shell overlay icons"));
parser.addOption(shellOverlayOption);
parser.addPositionalArgument(QStringLiteral("file"), QStringLiteral("The file to open."));
parser.addPositionalArgument(QStringLiteral("image_file_folder"), QStringLiteral("The folder to store the images."));
parser.process(app);
const QStringList &positionalArguments = parser.positionalArguments();
if (positionalArguments.isEmpty())
parser.showHelp(0);
QString imageFileRoot = positionalArguments.size() > 1 ? positionalArguments.at(1) : QDir::currentPath();
const QFileInfo imageFileRootInfo(imageFileRoot);
if (!imageFileRootInfo.isDir()) {
std::wcerr << imageFileRoot << " is not a directory.\n";
return 1;
}
const QString &sourceFile = positionalArguments.constFirst();
imageFileRoot = imageFileRootInfo.absoluteFilePath() + u'/' + QFileInfo(sourceFile).baseName();
const PixmapEntryList pixmaps = parser.isSet(shellIconOption)
? extractShellIcons(sourceFile, parser.isSet(shellOverlayOption))
: extractIcons(sourceFile, parser.isSet(largeIconOption));
for (const auto &entry : pixmaps) {
const QString fileName = imageFileRoot + entry.name + QLatin1String(".png");
if (!entry.pixmap.save(fileName)) {
std::wcerr << "Error writing image file " << fileName << ".\n";
return 1;
}
std::wcout << "Wrote " << QDir::toNativeSeparators(fileName) << ".\n";
}
return 0;
}*/

View File

@ -0,0 +1,13 @@
#pragma once
#include "../mischelpers_global.h"
struct PixmapEntry {
QString name;
QPixmap pixmap;
};
typedef QVector<PixmapEntry> PixmapEntryList;
MISCHELPERS_EXPORT PixmapEntryList extractIcons(const QString &sourceFile, bool large);
MISCHELPERS_EXPORT PixmapEntryList extractShellIcons(const QString &sourceFile, bool addOverlays);

View File

@ -0,0 +1,191 @@
#include "stdafx.h"
#include "ItemChooser.h"
CItemChooser::CItemChooser(const QString& Prompt, QWidget *parent)
: QDialog(parent)
{
this->setWindowTitle(tr("Item Chooser"));
m_pMainLayout = new QVBoxLayout();
this->setLayout(m_pMainLayout);
m_pLabel = new QLabel(Prompt.isNull() ? tr("Select items that will be used.") : Prompt, this);
m_pLabel->setWordWrap(true);
m_pMainLayout->addWidget(m_pLabel);
m_pCenterLayout = new QHBoxLayout();
m_pMainLayout->addLayout(m_pCenterLayout);
m_pListAll = new QListWidget(this);
m_pCenterLayout->addWidget(m_pListAll);
m_pListAll->setSelectionMode(QAbstractItemView::ExtendedSelection);
connect(m_pListAll, SIGNAL(itemDoubleClicked(QListWidgetItem*)), this, SLOT(OnAdd()));
m_pMidleLayout = new QVBoxLayout();
m_pCenterLayout->addLayout(m_pMidleLayout);
m_pMidleLayout->addItem(new QSpacerItem(20, 40, QSizePolicy::Minimum, QSizePolicy::Expanding));
m_pBtnAdd = new QPushButton(tr("Add >"), this);
connect(m_pBtnAdd, SIGNAL(pressed()), this, SLOT(OnAdd()));
m_pMidleLayout->addWidget(m_pBtnAdd);
m_pBtnRemove = new QPushButton(tr("< Remove"), this);
connect(m_pBtnRemove, SIGNAL(pressed()), this, SLOT(OnRemove()));
m_pMidleLayout->addWidget(m_pBtnRemove);
m_pMidleLayout->addItem(new QSpacerItem(20, 40, QSizePolicy::Minimum, QSizePolicy::Expanding));
m_pListChoosen = new QListWidget(this);
m_pCenterLayout->addWidget(m_pListChoosen);
m_pListChoosen->setSelectionMode(QAbstractItemView::ExtendedSelection);
connect(m_pListChoosen, SIGNAL(itemDoubleClicked(QListWidgetItem*)), this, SLOT(OnRemove()));
m_pRightLayout = new QVBoxLayout();
m_pCenterLayout->addLayout(m_pRightLayout);
m_pBtnUp = new QPushButton(tr("Move Up"), this);
connect(m_pBtnUp, SIGNAL(pressed()), this, SLOT(OnUp()));
m_pRightLayout->addWidget(m_pBtnUp);
m_pBtnDown = new QPushButton(tr("Move Down"), this);
connect(m_pBtnDown, SIGNAL(pressed()), this, SLOT(OnDown()));
m_pRightLayout->addWidget(m_pBtnDown);
m_pRightLayout->addItem(new QSpacerItem(20, 40, QSizePolicy::Minimum, QSizePolicy::Expanding));
m_InsertIndex = m_pMainLayout->count();
m_pButtonBox = new QDialogButtonBox(this);
m_pMainLayout->addWidget(m_pButtonBox);
m_pButtonBox->setStandardButtons(QDialogButtonBox::Cancel|QDialogButtonBox::Ok);
connect(m_pButtonBox, SIGNAL(accepted()), this, SLOT(accept()));
connect(m_pButtonBox, SIGNAL(rejected()), this, SLOT(reject()));
}
void CItemChooser::closeEvent(QCloseEvent *e)
{
this->deleteLater();
}
void CItemChooser::SetPrompt(const QString& Text)
{
m_pLabel->setText(Text);
}
void CItemChooser::AddWidgets(QList<QWidget*> Widgets)
{
foreach(QWidget* pWidget, Widgets)
AddWidget(pWidget);
}
void CItemChooser::AddWidget(QWidget* pWidget)
{
m_pMainLayout->insertWidget(m_InsertIndex++, pWidget);
}
void CItemChooser::AddItem(const QString& Label, const QVariant& Data)
{
QListWidgetItem* pItem = new QListWidgetItem(Label);
pItem->setData(Qt::UserRole, Data);
m_pListAll->addItem(pItem);
}
void CItemChooser::OnAdd()
{
foreach(QListWidgetItem* pItem, m_pListAll->selectedItems())
AddItem(pItem);
}
void CItemChooser::OnRemove()
{
foreach(QListWidgetItem* pItem, m_pListChoosen->selectedItems())
RemoveItem(pItem);
}
void CItemChooser::AddItem(QListWidgetItem* pItem)
{
pItem->setFlags(pItem->flags() & ~Qt::ItemIsSelectable & ~Qt::ItemIsEnabled);
if (m_pListChoosen->findItems(pItem->text(), Qt::MatchExactly).count() > 0)
return; // already added
QListWidgetItem* pChoosenItem = new QListWidgetItem(pItem->text());
pChoosenItem->setData(Qt::UserRole, pItem->data(Qt::UserRole));
m_pListChoosen->addItem(pChoosenItem);
}
void CItemChooser::RemoveItem(QListWidgetItem* pChoosenItem)
{
foreach(QListWidgetItem* pItem, m_pListAll->findItems(pChoosenItem->text(), Qt::MatchExactly))
pItem->setFlags(pItem->flags() | Qt::ItemIsSelectable | Qt::ItemIsEnabled);
delete pChoosenItem;
}
void CItemChooser::OnUp()
{
for (int i = 0; i < m_pListChoosen->count(); i++)
{
QListWidgetItem* pItem = m_pListChoosen->item(i);
if (!pItem->isSelected())
continue;
if (!MoveItem(pItem, -1))
break;
}
}
void CItemChooser::OnDown()
{
for (int i = m_pListChoosen->count()-1; i >= 0 ; i--)
{
QListWidgetItem* pItem = m_pListChoosen->item(i);
if (!pItem->isSelected())
continue;
if (!MoveItem(pItem, 1))
break;
}
}
bool CItemChooser::MoveItem(QListWidgetItem* pItem, int Pos)
{
int currIndex = m_pListChoosen->row(pItem);
QListWidgetItem *pPrev = m_pListChoosen->item(m_pListChoosen->row(pItem) + Pos);
if (!pPrev)
return false;
int prevIndex = m_pListChoosen->row(pPrev);
QListWidgetItem *pTemp = m_pListChoosen->takeItem(prevIndex);
m_pListChoosen->insertItem(prevIndex, pItem);
m_pListChoosen->insertItem(currIndex, pTemp);
return true;
}
QVariantList CItemChooser::GetChoosenItems()
{
QVariantList ChoosenItems;
for(int i=0; i < m_pListChoosen->count(); i++)
ChoosenItems.append(m_pListChoosen->item(i)->data(Qt::UserRole));
return ChoosenItems;
}
void CItemChooser::ChooseItems(const QVariantList& ChoosenItems)
{
foreach(const QVariant& Data, ChoosenItems)
ChooseItem(Data);
}
void CItemChooser::ChooseItem(const QVariant& Data)
{
QListWidgetItem* pItem = NULL;
for (int i = 0; i < m_pListAll->count(); i++)
{
if (m_pListAll->item(i)->data(Qt::UserRole) == Data)
{
pItem = m_pListAll->item(i);
break;
}
}
if (pItem)
AddItem(pItem);
}

View File

@ -0,0 +1,61 @@
#pragma once
#include <QtWidgets/QMainWindow>
#include <QListWidgetItem>
#include "../mischelpers_global.h"
class MISCHELPERS_EXPORT CItemChooser : public QDialog
{
Q_OBJECT
public:
CItemChooser(const QString& Prompt = QString(), QWidget *parent = Q_NULLPTR);
void SetPrompt(const QString& Text);
void AddWidgets(QList<QWidget*> Widgets);
void AddWidget(QWidget* pWidget);
void AddItem(const QString& Label, const QVariant& Data);
void ChooseItems(const QVariantList& ChoosenItems);
void ChooseItem(const QVariant& Data);
QVariantList GetChoosenItems();
private slots:
void OnAdd();
void OnRemove();
void OnUp();
void OnDown();
protected:
void closeEvent(QCloseEvent *e);
void AddItem(QListWidgetItem* pItem);
void RemoveItem(QListWidgetItem* pChoosenItem);
bool MoveItem(QListWidgetItem* pItem, int Pos);
private:
QVBoxLayout* m_pMainLayout;
QLabel* m_pLabel;
QHBoxLayout* m_pCenterLayout;
QListWidget* m_pListAll;
QVBoxLayout* m_pMidleLayout;
QPushButton* m_pBtnAdd;
QPushButton* m_pBtnRemove;
QListWidget* m_pListChoosen;
QVBoxLayout* m_pRightLayout;
QPushButton* m_pBtnUp;
QPushButton* m_pBtnDown;
QDialogButtonBox* m_pButtonBox;
int m_InsertIndex;
};

View File

@ -0,0 +1,224 @@
#include "stdafx.h"
#include "KeyValueInputDialog.h"
#include <QPushButton>
#include <QCheckBox>
#include <QHBoxLayout>
#include <QLabel>
#include <QDebug>
class CKeyValueInputDialogPrivate
{
public:
CKeyValueInputDialogPrivate(QDialog *q)
: clickedButton(0)
{
QSizePolicy sizePolicy(QSizePolicy::Minimum, QSizePolicy::Preferred);
pixmapLabel = new QLabel(q);
sizePolicy.setHorizontalStretch(0);
sizePolicy.setVerticalStretch(0);
sizePolicy.setHeightForWidth(pixmapLabel->sizePolicy().hasHeightForWidth());
pixmapLabel->setSizePolicy(sizePolicy);
pixmapLabel->setVisible(false);
QSpacerItem *pixmapSpacer =
new QSpacerItem(0, 5, QSizePolicy::Minimum, QSizePolicy::MinimumExpanding);
messageLabel = new QLabel(q);
messageLabel->setMinimumSize(QSize(300, 0));
messageLabel->setWordWrap(true);
messageLabel->setOpenExternalLinks(true);
messageLabel->setTextInteractionFlags(Qt::LinksAccessibleByKeyboard|Qt::LinksAccessibleByMouse);
QSpacerItem *buttonSpacer =
new QSpacerItem(0, 1, QSizePolicy::Minimum, QSizePolicy::Minimum);
keyLabel = new QLabel(q);
keyLabel->setText("Key:");
keyEdit = new QLineEdit(q);
valueLabel = new QLabel(q);
valueLabel->setText("Value:");
valueEdit = new QTextEdit(q);
buttonBox = new QDialogButtonBox(q);
buttonBox->setOrientation(Qt::Horizontal);
buttonBox->setStandardButtons(QDialogButtonBox::Cancel|QDialogButtonBox::Ok);
QVBoxLayout *verticalLayout = new QVBoxLayout();
verticalLayout->addWidget(pixmapLabel);
verticalLayout->addItem(pixmapSpacer);
QHBoxLayout *horizontalLayout_2 = new QHBoxLayout();
horizontalLayout_2->addLayout(verticalLayout);
horizontalLayout_2->addWidget(messageLabel);
QFormLayout *horizontalLayout = new QFormLayout();
horizontalLayout->addRow(keyLabel, keyEdit);
horizontalLayout->addRow(valueLabel, valueEdit);
QVBoxLayout *verticalLayout_2 = new QVBoxLayout(q);
verticalLayout_2->addLayout(horizontalLayout_2);
verticalLayout_2->addLayout(horizontalLayout);
verticalLayout_2->addItem(buttonSpacer);
verticalLayout_2->addWidget(buttonBox);
}
QLabel *pixmapLabel;
QLabel *messageLabel;
QLabel *keyLabel;
QLineEdit* keyEdit;
QLabel *valueLabel;
QTextEdit* valueEdit;
QDialogButtonBox *buttonBox;
QAbstractButton *clickedButton;
};
CKeyValueInputDialog::CKeyValueInputDialog(QWidget *parent) :
QDialog(parent),
d(new CKeyValueInputDialogPrivate(this))
{
setModal(true);
setWindowFlags(windowFlags() & ~Qt::WindowContextHelpButtonHint);
connect(d->buttonBox, SIGNAL(accepted()), SLOT(accept()));
connect(d->buttonBox, SIGNAL(rejected()), SLOT(reject()));
connect(d->buttonBox, SIGNAL(clicked(QAbstractButton*)),
SLOT(slotClicked(QAbstractButton*)));
}
CKeyValueInputDialog::~CKeyValueInputDialog()
{
delete d;
}
void CKeyValueInputDialog::slotClicked(QAbstractButton *b)
{
d->clickedButton = b;
}
QAbstractButton *CKeyValueInputDialog::clickedButton() const
{
return d->clickedButton;
}
QDialogButtonBox::StandardButton CKeyValueInputDialog::clickedStandardButton() const
{
if (d->clickedButton)
return d->buttonBox->standardButton(d->clickedButton);
return QDialogButtonBox::NoButton;
}
QString CKeyValueInputDialog::text() const
{
return d->messageLabel->text();
}
void CKeyValueInputDialog::setText(const QString &t)
{
d->messageLabel->setText(t);
}
QString CKeyValueInputDialog::keyLabel() const
{
return d->keyLabel->text();
}
void CKeyValueInputDialog::setKeyLabel(const QString &t)
{
return d->keyLabel->setText(t);
}
QString CKeyValueInputDialog::key() const
{
return d->keyEdit->text();
}
void CKeyValueInputDialog::setKey(const QString &t)
{
return d->keyEdit->setText(t);
}
bool CKeyValueInputDialog::keyReadOnly() const
{
return d->keyEdit->isReadOnly();
}
void CKeyValueInputDialog::setKeyReadOnly(bool r)
{
return d->keyEdit->setReadOnly(r);
}
QString CKeyValueInputDialog::valueLabel() const
{
return d->valueLabel->text();
}
void CKeyValueInputDialog::setValueLabel(const QString &t)
{
return d->valueLabel->setText(t);
}
QString CKeyValueInputDialog::value() const
{
return d->valueEdit->toPlainText();
}
void CKeyValueInputDialog::setValue(const QString &t)
{
return d->valueEdit->setText(t);
}
QPixmap CKeyValueInputDialog::iconPixmap() const
{
if (const QPixmap *p = d->pixmapLabel->pixmap())
return QPixmap(*p);
return QPixmap();
}
void CKeyValueInputDialog::setIconPixmap(const QPixmap &p)
{
d->pixmapLabel->setPixmap(p);
d->pixmapLabel->setVisible(!p.isNull());
}
QDialogButtonBox::StandardButtons CKeyValueInputDialog::standardButtons() const
{
return d->buttonBox->standardButtons();
}
void CKeyValueInputDialog::setStandardButtons(QDialogButtonBox::StandardButtons s)
{
d->buttonBox->setStandardButtons(s);
}
QPushButton *CKeyValueInputDialog::button(QDialogButtonBox::StandardButton b) const
{
return d->buttonBox->button(b);
}
QPushButton *CKeyValueInputDialog::addButton(const QString &text, QDialogButtonBox::ButtonRole role)
{
return d->buttonBox->addButton(text, role);
}
QDialogButtonBox::StandardButton CKeyValueInputDialog::defaultButton() const
{
foreach (QAbstractButton *b, d->buttonBox->buttons())
if (QPushButton *pb = qobject_cast<QPushButton *>(b))
if (pb->isDefault())
return d->buttonBox->standardButton(pb);
return QDialogButtonBox::NoButton;
}
void CKeyValueInputDialog::setDefaultButton(QDialogButtonBox::StandardButton s)
{
if (QPushButton *b = d->buttonBox->button(s)) {
b->setDefault(true);
b->setFocus();
}
}

View File

@ -0,0 +1,67 @@
#ifndef KEYVALUEINPUTDIALOG_H
#define KEYVALUEINPUTDIALOG_H
#include <QDialogButtonBox>
#include <QMessageBox>
class CKeyValueInputDialogPrivate;
#include "../mischelpers_global.h"
class MISCHELPERS_EXPORT CKeyValueInputDialog : public QDialog
{
Q_OBJECT
Q_PROPERTY(QString text READ text WRITE setText)
Q_PROPERTY(QPixmap iconPixmap READ iconPixmap WRITE setIconPixmap)
Q_PROPERTY(QDialogButtonBox::StandardButtons buttons READ standardButtons WRITE setStandardButtons)
Q_PROPERTY(QDialogButtonBox::StandardButton defaultButton READ defaultButton WRITE setDefaultButton)
public:
explicit CKeyValueInputDialog(QWidget *parent = NULL);
virtual ~CKeyValueInputDialog();
QString text() const;
void setText(const QString &);
QString keyLabel() const;
void setKeyLabel(const QString &);
QString key() const;
void setKey(const QString &);
bool keyReadOnly() const;
void setKeyReadOnly(bool);
QString valueLabel() const;
void setValueLabel(const QString &);
QString value() const;
void setValue(const QString &);
QDialogButtonBox::StandardButtons standardButtons() const;
void setStandardButtons(QDialogButtonBox::StandardButtons s);
QPushButton *button(QDialogButtonBox::StandardButton b) const;
QPushButton *addButton(const QString &text, QDialogButtonBox::ButtonRole role);
QDialogButtonBox::StandardButton defaultButton() const;
void setDefaultButton(QDialogButtonBox::StandardButton s);
// See static QMessageBox::standardPixmap()
QPixmap iconPixmap() const;
void setIconPixmap (const QPixmap &p);
// Query the result
QAbstractButton *clickedButton() const;
QDialogButtonBox::StandardButton clickedStandardButton() const;
private slots:
void slotClicked(QAbstractButton *b);
private:
CKeyValueInputDialogPrivate *d;
};
#endif // HCOMBODIALOG_H

View File

@ -0,0 +1,305 @@
#include "stdafx.h"
#include "ListItemModel.h"
#define FIRST_COLUMN 0
bool CListItemModel::m_DarkMode = false;
CListItemModel::CListItemModel(QObject *parent)
: QAbstractItemModelEx(parent)
{
m_bUseIcons = false;
}
CListItemModel::~CListItemModel()
{
foreach(SListNode* pNode, m_List)
delete pNode;
}
int CListItemModel::GetRow(SListNode* pNode) const
{
int Index = m_RevList.value(pNode, -1);
ASSERT(Index != -1);
ASSERT(m_List[Index] == pNode);
return Index;
}
void CSimpleListModel::Sync(QList<QVariantMap> List)
{
QList<SListNode*> New;
QHash<QVariant, SListNode*> Old = m_Map;
foreach (const QVariantMap& Cur, List)
{
QVariant ID = Cur["ID"];
int Row = -1;
SListNode* pNode = static_cast<SListNode*>(Old[ID]);
if(!pNode)
{
pNode = static_cast<SListNode*>(MkNode(ID));
pNode->Values.resize(columnCount());
pNode->IsBold = Cur["IsBold"].toBool();
pNode->Icon = Cur["Icon"];
New.append(pNode);
}
else
{
Old[ID] = NULL;
Row = GetRow(pNode);
}
int Col = 0;
bool State = false;
bool Changed = false;
QVariantMap Values = Cur["Values"].toMap();
for(int section = FIRST_COLUMN; section < columnCount(); section++)
{
if (!m_Columns.contains(section))
continue; // ignore columns which are hidden
QVariant Value = Values[QString::number(section)];
SListNode::SValue& ColValue = pNode->Values[section];
if (ColValue.Raw != Value)
{
Changed = true;
ColValue.Raw = Value;
//ColValue.Formated =
}
if(State != Changed)
{
if(State && Row != -1)
emit dataChanged(createIndex(Row, Col), createIndex(Row, section-1));
State = Changed;
Col = section;
}
Changed = false;
}
if(State && Row != -1)
emit dataChanged(createIndex(Row, Col, pNode), createIndex(Row, columnCount()-1, pNode));
}
CListItemModel::Sync(New, Old);
}
void CListItemModel::Sync(QList<SListNode*>& New, QHash<QVariant, SListNode*>& Old)
{
int Removed = 0;
int Begin = -1;
int End = -1;
for(int i = m_List.count()-1; i >= -1; i--)
{
QVariant ID = i >= 0 ? m_List[i]->ID : QVariant();
if(!ID.isNull() && (Old.value(ID) != NULL)) // remove it
{
m_Map.remove(ID);
if(End == -1)
End = i;
}
else if(End != -1) // keep it and remove whatis to be removed at once
{
Begin = i + 1;
beginRemoveRows(QModelIndex(), Begin, End);
for (int j = End; j >= Begin; j--)
{
Removed++;
SListNode* pNode = m_List.takeAt(j);
m_RevList.remove(pNode);
delete pNode;
}
endRemoveRows();
End = -1;
Begin = -1;
}
}
// if something was removed we need to update the row cache
if (Removed > 0)
{
ASSERT(m_RevList.size() == m_List.size());
for (int i = 0; i < m_List.count(); i++)
m_RevList[m_List[i]] = i;
}
Begin = m_List.count();
for(QList<SListNode*>::iterator I = New.begin(); I != New.end(); I++)
{
SListNode* pNode = *I;
m_Map.insert(pNode->ID, pNode);
int Index = m_List.size();
m_List.append(pNode);
m_RevList.insert(pNode, Index);
}
End = m_List.count();
if(Begin < End)
{
beginInsertRows(QModelIndex(), Begin, End-1);
endInsertRows();
}
}
QModelIndex CListItemModel::FindIndex(const QVariant& ID)
{
if(SListNode* pNode = m_Map.value(ID))
{
int row = m_List.indexOf(pNode);
ASSERT(row != -1);
return createIndex(row, FIRST_COLUMN, pNode);
}
return QModelIndex();
}
void CListItemModel::Clear()
{
//beginResetModel();
if (rowCount() == 0)
return;
beginRemoveRows(QModelIndex(), 0, rowCount()-1);
foreach(SListNode* pNode, m_List)
delete pNode;
m_List.clear();
m_RevList.clear();
m_Map.clear();
endRemoveRows();
//endResetModel();
}
QVariant CListItemModel::data(const QModelIndex &index, int role) const
{
return Data(index, role, index.column());
}
QVariant CListItemModel::Data(const QModelIndex &index, int role, int section) const
{
if (!index.isValid())
return QVariant();
//if(role == Qt::SizeHintRole )
// return QSize(64,16); // for fixing height
SListNode* pNode = static_cast<SListNode*>(index.internalPointer());
switch(role)
{
case Qt::DisplayRole:
{
SListNode::SValue& Value = pNode->Values[section];
return Value.Formated.isValid() ? Value.Formated : Value.Raw;
}
case Qt::EditRole: // sort role
{
return pNode->Values[section].Raw;
}
case Qt::ToolTipRole:
{
QString ToolTip;
emit ToolTipCallback(pNode->ID, ToolTip);
if(!ToolTip.isNull())
return ToolTip;
break;
}
case Qt::DecorationRole:
{
if (m_bUseIcons && section == FIRST_COLUMN)
return pNode->Icon.isValid() ? pNode->Icon : GetDefaultIcon();
break;
}
case Qt::FontRole:
{
if (section == FIRST_COLUMN && pNode->IsBold)
{
QFont fnt;
fnt.setBold(true);
return fnt;
}
break;
}
case Qt::BackgroundRole:
{
if(!m_DarkMode)
return pNode->Color.isValid() ? pNode->Color : QVariant();
break;
}
case Qt::ForegroundRole:
{
if(m_DarkMode)
return pNode->Color.isValid() ? pNode->Color : QVariant();
else if (pNode->IsGray)
{
QColor Color = Qt::darkGray;
return QBrush(Color);
}
break;
}
case Qt::UserRole:
{
switch(section)
{
case FIRST_COLUMN: return pNode->ID;
}
break;
}
}
return QVariant();
}
Qt::ItemFlags CListItemModel::flags(const QModelIndex &index) const
{
if (!index.isValid())
return 0;
return Qt::ItemIsEnabled | Qt::ItemIsSelectable;
}
QModelIndex CListItemModel::index(int row, int column, const QModelIndex &parent) const
{
if (!hasIndex(row, column, parent))
return QModelIndex();
if (parent.isValid())
return QModelIndex();
if(m_List.count() > row)
return createIndex(row, column, m_List[row]);
return QModelIndex();
}
QModelIndex CListItemModel::parent(const QModelIndex &index) const
{
return QModelIndex();
}
int CListItemModel::rowCount(const QModelIndex &parent) const
{
if (parent.column() > 0)
return 0;
if (parent.isValid())
return 0;
return m_List.count();
}
int CSimpleListModel::columnCount(const QModelIndex &parent) const
{
return m_Headers.count();
}
QVariant CSimpleListModel::headerData(int section, Qt::Orientation orientation, int role) const
{
if (orientation == Qt::Horizontal && role == Qt::DisplayRole)
{
if (section < m_Headers.size())
return m_Headers.at(section);
}
return QVariant();
}

View File

@ -0,0 +1,98 @@
#pragma once
#include "TreeViewEx.h"
#include "../mischelpers_global.h"
class MISCHELPERS_EXPORT CListItemModel : public QAbstractItemModelEx
{
Q_OBJECT
public:
CListItemModel(QObject *parent = 0);
virtual ~CListItemModel();
void SetUseIcons(bool bUseIcons) { m_bUseIcons = bUseIcons; }
static void SetDarkMode(bool bDark) { m_DarkMode = bDark;}
QModelIndex FindIndex(const QVariant& ID);
QVariant Data(const QModelIndex &index, int role, int section) const;
// derived functions
virtual QVariant data(const QModelIndex &index, int role) const;
virtual Qt::ItemFlags flags(const QModelIndex &index) const;
virtual QModelIndex index(int row, int column, const QModelIndex &parent = QModelIndex()) const;
virtual QModelIndex parent(const QModelIndex &index) const;
virtual int rowCount(const QModelIndex &parent = QModelIndex()) const;
virtual int columnCount(const QModelIndex &parent = QModelIndex()) const = 0;
virtual QVariant headerData(int section, Qt::Orientation orientation, int role = Qt::DisplayRole) const = 0;
public slots:
void Clear();
signals:
void ToolTipCallback(const QVariant& ID, QString& ToolTip) const;
protected:
struct SListNode
{
SListNode(const QVariant& Id)
{
ID = Id;
IsBold = false;
IsGray = false;
}
virtual ~SListNode()
{
}
QVariant ID;
QVariant Icon;
bool IsBold;
bool IsGray;
QColor Color;
struct SValue
{
QVariant Raw;
QVariant Formated;
};
QVector<SValue> Values;
};
virtual SListNode* MkNode(const QVariant& Id) = 0; // { return new SListNode(Id); }
void Sync(QList<SListNode*>& New, QHash<QVariant, SListNode*>& Old);
virtual QVariant GetDefaultIcon() const { return QVariant(); }
int GetRow(SListNode* pNode) const;
QList<SListNode*> m_List;
QHash<void*, int> m_RevList;
QHash<QVariant, SListNode*> m_Map;
bool m_bUseIcons;
static bool m_DarkMode;
};
class MISCHELPERS_EXPORT CSimpleListModel : public CListItemModel
{
Q_OBJECT
public:
CSimpleListModel(QObject *parent = 0) : CListItemModel(parent) {}
void Sync(QList<QVariantMap> List);
void setHeaderLabels(const QStringList& Columns) { m_Headers = Columns; }
virtual int columnCount(const QModelIndex &parent = QModelIndex()) const;
virtual QVariant headerData(int section, Qt::Orientation orientation, int role = Qt::DisplayRole) const;
protected:
virtual SListNode* MkNode(const QVariant& Id) { return new SListNode(Id); }
QStringList m_Headers;
};

View File

@ -0,0 +1,169 @@
#include "stdafx.h"
#include "MultiLineInputDialog.h"
#include <QPushButton>
#include <QCheckBox>
#include <QHBoxLayout>
#include <QLabel>
#include <QDebug>
class CMultiLineInputDialogPrivate
{
public:
CMultiLineInputDialogPrivate(QDialog *q)
: clickedButton(0)
{
QSizePolicy sizePolicy(QSizePolicy::Minimum, QSizePolicy::Preferred);
pixmapLabel = new QLabel(q);
sizePolicy.setHorizontalStretch(0);
sizePolicy.setVerticalStretch(0);
sizePolicy.setHeightForWidth(pixmapLabel->sizePolicy().hasHeightForWidth());
pixmapLabel->setSizePolicy(sizePolicy);
pixmapLabel->setVisible(false);
QSpacerItem *pixmapSpacer =
new QSpacerItem(0, 5, QSizePolicy::Minimum, QSizePolicy::MinimumExpanding);
messageLabel = new QLabel(q);
messageLabel->setMinimumSize(QSize(300, 0));
messageLabel->setWordWrap(true);
messageLabel->setOpenExternalLinks(true);
messageLabel->setTextInteractionFlags(Qt::LinksAccessibleByKeyboard|Qt::LinksAccessibleByMouse);
QSpacerItem *buttonSpacer =
new QSpacerItem(0, 1, QSizePolicy::Minimum, QSizePolicy::Minimum);
edit = new QPlainTextEdit(q);
buttonBox = new QDialogButtonBox(q);
buttonBox->setOrientation(Qt::Horizontal);
buttonBox->setStandardButtons(QDialogButtonBox::Cancel|QDialogButtonBox::Ok);
QVBoxLayout *verticalLayout = new QVBoxLayout();
verticalLayout->addWidget(pixmapLabel);
verticalLayout->addItem(pixmapSpacer);
QHBoxLayout *horizontalLayout_2 = new QHBoxLayout();
horizontalLayout_2->addLayout(verticalLayout);
horizontalLayout_2->addWidget(messageLabel);
QVBoxLayout *verticalLayout_2 = new QVBoxLayout(q);
verticalLayout_2->addLayout(horizontalLayout_2);
verticalLayout_2->addWidget(edit);
verticalLayout_2->addItem(buttonSpacer);
verticalLayout_2->addWidget(buttonBox);
}
QLabel *pixmapLabel;
QLabel *messageLabel;
QPlainTextEdit* edit;
QDialogButtonBox *buttonBox;
QAbstractButton *clickedButton;
};
CMultiLineInputDialog::CMultiLineInputDialog(QWidget *parent) :
QDialog(parent),
d(new CMultiLineInputDialogPrivate(this))
{
setModal(true);
setWindowFlags(windowFlags() & ~Qt::WindowContextHelpButtonHint);
connect(d->buttonBox, SIGNAL(accepted()), SLOT(accept()));
connect(d->buttonBox, SIGNAL(rejected()), SLOT(reject()));
connect(d->buttonBox, SIGNAL(clicked(QAbstractButton*)),
SLOT(slotClicked(QAbstractButton*)));
}
CMultiLineInputDialog::~CMultiLineInputDialog()
{
delete d;
}
void CMultiLineInputDialog::slotClicked(QAbstractButton *b)
{
d->clickedButton = b;
}
QAbstractButton *CMultiLineInputDialog::clickedButton() const
{
return d->clickedButton;
}
QDialogButtonBox::StandardButton CMultiLineInputDialog::clickedStandardButton() const
{
if (d->clickedButton)
return d->buttonBox->standardButton(d->clickedButton);
return QDialogButtonBox::NoButton;
}
QString CMultiLineInputDialog::text() const
{
return d->messageLabel->text();
}
void CMultiLineInputDialog::setText(const QString &t)
{
d->messageLabel->setText(t);
}
QString CMultiLineInputDialog::value() const
{
return d->edit->toPlainText();
}
void CMultiLineInputDialog::setValue(const QString &t)
{
d->edit->setPlainText(t);
}
QPixmap CMultiLineInputDialog::iconPixmap() const
{
if (const QPixmap *p = d->pixmapLabel->pixmap())
return QPixmap(*p);
return QPixmap();
}
void CMultiLineInputDialog::setIconPixmap(const QPixmap &p)
{
d->pixmapLabel->setPixmap(p);
d->pixmapLabel->setVisible(!p.isNull());
}
QDialogButtonBox::StandardButtons CMultiLineInputDialog::standardButtons() const
{
return d->buttonBox->standardButtons();
}
void CMultiLineInputDialog::setStandardButtons(QDialogButtonBox::StandardButtons s)
{
d->buttonBox->setStandardButtons(s);
}
QPushButton *CMultiLineInputDialog::button(QDialogButtonBox::StandardButton b) const
{
return d->buttonBox->button(b);
}
QPushButton *CMultiLineInputDialog::addButton(const QString &text, QDialogButtonBox::ButtonRole role)
{
return d->buttonBox->addButton(text, role);
}
QDialogButtonBox::StandardButton CMultiLineInputDialog::defaultButton() const
{
foreach (QAbstractButton *b, d->buttonBox->buttons())
if (QPushButton *pb = qobject_cast<QPushButton *>(b))
if (pb->isDefault())
return d->buttonBox->standardButton(pb);
return QDialogButtonBox::NoButton;
}
void CMultiLineInputDialog::setDefaultButton(QDialogButtonBox::StandardButton s)
{
if (QPushButton *b = d->buttonBox->button(s)) {
b->setDefault(true);
b->setFocus();
}
}

View File

@ -0,0 +1,55 @@
#ifndef MULTILINEINPUTDIALOG_H
#define MULTILINEINPUTDIALOG_H
#include <QDialogButtonBox>
#include <QMessageBox>
class CMultiLineInputDialogPrivate;
#include "../mischelpers_global.h"
class MISCHELPERS_EXPORT CMultiLineInputDialog : public QDialog
{
Q_OBJECT
Q_PROPERTY(QString text READ text WRITE setText)
Q_PROPERTY(QPixmap iconPixmap READ iconPixmap WRITE setIconPixmap)
Q_PROPERTY(QDialogButtonBox::StandardButtons buttons READ standardButtons WRITE setStandardButtons)
Q_PROPERTY(QDialogButtonBox::StandardButton defaultButton READ defaultButton WRITE setDefaultButton)
public:
explicit CMultiLineInputDialog(QWidget *parent = NULL);
virtual ~CMultiLineInputDialog();
QString text() const;
void setText(const QString &);
QString value() const;
void setValue(const QString &);
QDialogButtonBox::StandardButtons standardButtons() const;
void setStandardButtons(QDialogButtonBox::StandardButtons s);
QPushButton *button(QDialogButtonBox::StandardButton b) const;
QPushButton *addButton(const QString &text, QDialogButtonBox::ButtonRole role);
QDialogButtonBox::StandardButton defaultButton() const;
void setDefaultButton(QDialogButtonBox::StandardButton s);
// See static QMessageBox::standardPixmap()
QPixmap iconPixmap() const;
void setIconPixmap (const QPixmap &p);
// Query the result
QAbstractButton *clickedButton() const;
QDialogButtonBox::StandardButton clickedStandardButton() const;
private slots:
void slotClicked(QAbstractButton *b);
private:
CMultiLineInputDialogPrivate *d;
};
#endif // HMULTILINEINPUTDIALOG_H

View File

@ -0,0 +1,220 @@
#include "stdafx.h"
#include "PanelView.h"
bool CPanelView::m_SimpleFormat = false;
int CPanelView::m_MaxCellWidth = 0;
QString CPanelView::m_CellSeparator = "\t";
CPanelView::CPanelView(QWidget *parent)
:QWidget(parent)
{
//m_CopyAll = false;
m_pMenu = new QMenu();
}
CPanelView::~CPanelView()
{
}
void CPanelView::AddPanelItemsToMenu(bool bAddSeparator)
{
if(bAddSeparator)
m_pMenu->addSeparator();
m_pCopyCell = m_pMenu->addAction(tr("Copy Cell"), this, SLOT(OnCopyCell()));
m_pCopyRow = m_pMenu->addAction(tr("Copy Row"), this, SLOT(OnCopyRow()));
m_pCopyRow->setShortcut(QKeySequence::Copy);
m_pCopyRow->setShortcutContext(Qt::WidgetWithChildrenShortcut);
this->addAction(m_pCopyRow);
m_pCopyPanel = m_pMenu->addAction(tr("Copy Panel"), this, SLOT(OnCopyPanel()));
}
void CPanelView::OnMenu(const QPoint& Point)
{
QModelIndex Index = GetView()->currentIndex();
m_pCopyCell->setEnabled(Index.isValid());
m_pCopyRow->setEnabled(Index.isValid());
m_pMenu->popup(QCursor::pos());
}
void CPanelView::OnCopyCell()
{
QAbstractItemModel* pModel = GetModel();
QTreeView * pView = GetView();
QModelIndex Index = pView->currentIndex();
QModelIndex ModelIndex = MapToSource(Index);
int Column = ModelIndex.column();
QList<QStringList> Rows;
foreach(const QModelIndex& Index, pView->selectionModel()->selectedIndexes())
{
if (Index.column() != Column)
continue;
QModelIndex CurIndex = pModel->index(Index.row(), Column, Index.parent());
QString Cell = pModel->data(CurIndex, Qt::DisplayRole).toString();
Rows.append(QStringList() << Cell);
}
FormatAndCopy(Rows, false);
}
void CPanelView::OnCopyRow()
{
QAbstractItemModel* pModel = GetModel();
QTreeView * pView = GetView();
int Column = 0; // find first not hidden column
for (int i = 0; i < pModel->columnCount(); i++)
{
if (!pView->isColumnHidden(i) || m_ForcedColumns.contains(i))
{
Column = i;
break;
}
}
QList<QStringList> Rows;
foreach(const QModelIndex& Index, pView->selectionModel()->selectedIndexes())
{
if (Index.column() != Column)
continue;
QModelIndex ModelIndex = MapToSource(Index);
Rows.append(CopyRow(ModelIndex));
}
FormatAndCopy(Rows);
}
QStringList CPanelView::CopyHeader()
{
QAbstractItemModel* pModel = GetModel();
QTreeView * pView = GetView();
QStringList Headder;
for (int i = 0; i < pModel->columnCount(); i++)
{
if (/*!m_CopyAll &&*/ pView->isColumnHidden(i) && !m_ForcedColumns.contains(i))
continue;
QString Cell = pModel->headerData(i, Qt::Horizontal, Qt::DisplayRole).toString();
if (!m_SimpleFormat)
Cell = "|" + Cell + "|";
Headder.append(Cell);
}
return Headder;
}
QStringList CPanelView::CopyRow(const QModelIndex& ModelIndex, int Level)
{
QAbstractItemModel* pModel = GetModel();
QTreeView * pView = GetView();
QStringList Cells;
for (int i = 0; i < pModel->columnCount(); i++)
{
if (/*!m_CopyAll &&*/ pView->isColumnHidden(i) && !m_ForcedColumns.contains(i))
continue;
QModelIndex CellIndex = pModel->index(ModelIndex.row(), i, ModelIndex.parent());
QString Cell = pModel->data(CellIndex, Qt::DisplayRole).toString();
if (Level && i == 0)
Cell.prepend(QString(Level, '_') + " ");
Cells.append(Cell);
}
return Cells;
}
void CPanelView::RecursiveCopyPanel(const QModelIndex& ModelIndex, QList<QStringList>& Rows, int Level)
{
QAbstractItemModel* pModel = GetModel();
Rows.append(CopyRow(ModelIndex, Level));
for (int i = 0; i < pModel->rowCount(ModelIndex); i++)
{
QModelIndex SubIndex = pModel->index(i, 0, ModelIndex);
RecursiveCopyPanel(SubIndex, Rows, Level + 1);
}
}
void CPanelView::OnCopyPanel()
{
QAbstractItemModel* pModel = GetModel();
QList<QStringList> Rows;
for (int i = 0; i < pModel->rowCount(); ++i)
{
QModelIndex ModelIndex = pModel->index(i, 0);
RecursiveCopyPanel(ModelIndex, Rows);
}
FormatAndCopy(Rows);
}
void CPanelView::FormatAndCopy(QList<QStringList> Rows, bool Headder)
{
int RowCount = Rows.length();
if (Headder)
{
Rows.prepend(QStringList());
Rows.prepend(CopyHeader());
Rows.prepend(QStringList());
}
QStringList TextRows;
if (m_SimpleFormat || !Headder)
{
foreach(const QStringList& Row, Rows)
TextRows.append(Row.join(m_CellSeparator));
}
else if(Rows.size() > (Headder ? 3 : 0))
{
int Columns = Rows[Headder ? 3 : 0].count();
QVector<int> ColumnWidths(Columns, 0);
foreach(const QStringList& Row, Rows)
{
for (int i = 0; i < Min(Row.count(), Columns); i++)
{
int CellWidth = Row[i].length();
if (ColumnWidths[i] < CellWidth)
ColumnWidths[i] = CellWidth;
}
}
foreach(const QStringList& Row, Rows)
{
if (m_MaxCellWidth != 0 && RowCount > 1)
{
for (int Pos = 0;;Pos += m_MaxCellWidth)
{
bool More = false;
QString RowText;
for (int i = 0; i < Min(Row.count(), Columns); i++)
{
if (Row[i].length() > Pos)
RowText.append(Row[i].mid(Pos, m_MaxCellWidth).leftJustified(Min(m_MaxCellWidth, ColumnWidths[i]) + 3));
else
RowText.append(QString(Min(m_MaxCellWidth, ColumnWidths[i]) + 3, ' '));
if (Row[i].length() > Pos + m_MaxCellWidth)
More = true;
}
TextRows.append(RowText);
if (!More)
break;
}
}
else
{
QString RowText;
for (int i = 0; i < Min(Row.count(), Columns); i++)
RowText.append(Row[i].leftJustified(ColumnWidths[i] + 3));
TextRows.append(RowText);
}
}
}
QApplication::clipboard()->setText(TextRows.join("\n"));
}

View File

@ -0,0 +1,170 @@
#pragma once
#include "../mischelpers_global.h"
class MISCHELPERS_EXPORT CPanelView : public QWidget
{
Q_OBJECT
public:
CPanelView(QWidget *parent = 0);
virtual ~CPanelView();
static void SetSimpleFormat(bool bSimple) { m_SimpleFormat = bSimple; }
static void SetMaxCellWidth(int iMaxWidth) { m_MaxCellWidth = iMaxWidth; }
static void SetCellSeparator(const QString& Sep) { m_CellSeparator = Sep; }
protected slots:
virtual void OnMenu(const QPoint& Point);
virtual void OnCopyCell();
virtual void OnCopyRow();
virtual void OnCopyPanel();
virtual QTreeView* GetView() = 0;
virtual QAbstractItemModel* GetModel() = 0;
virtual QModelIndex MapToSource(const QModelIndex& Model) { return Model; }
static QModelIndexList MapToSource(QModelIndexList Indexes, QSortFilterProxyModel* pProxy) {
for (int i = 0; i < Indexes.count(); i++)
Indexes[i] = pProxy->mapToSource(Indexes[i]);
return Indexes;
}
virtual void AddPanelItemsToMenu(bool bAddSeparator = true);
virtual void ForceColumn(int column, bool bSet = true) { if (bSet) m_ForcedColumns.insert(column); else m_ForcedColumns.remove(column); }
virtual QStringList CopyHeader();
virtual QStringList CopyRow(const QModelIndex& ModelIndex, int Level = 0);
virtual void RecursiveCopyPanel(const QModelIndex& ModelIndex, QList<QStringList>& Rows, int Level = 0);
protected:
void FormatAndCopy(QList<QStringList> Rows, bool Headder = true);
QMenu* m_pMenu;
QAction* m_pCopyCell;
QAction* m_pCopyRow;
QAction* m_pCopyPanel;
//bool m_CopyAll;
QSet<int> m_ForcedColumns;
static bool m_SimpleFormat;
static int m_MaxCellWidth;
static QString m_CellSeparator;
};
template <class T>
class CPanelWidget : public CPanelView
{
public:
CPanelWidget(QWidget *parent = 0) : CPanelView(parent)
{
m_pMainLayout = new QVBoxLayout();
m_pMainLayout->setMargin(0);
this->setLayout(m_pMainLayout);
m_pTreeList = new T();
m_pTreeList->setContextMenuPolicy(Qt::CustomContextMenu);
connect(m_pTreeList, SIGNAL(customContextMenuRequested( const QPoint& )), this, SLOT(OnMenu(const QPoint &)));
m_pMainLayout->addWidget(m_pTreeList);
m_pTreeList->setMinimumHeight(50);
AddPanelItemsToMenu();
m_pLastAction = m_pMenu->actions()[0];
}
virtual QMenu* GetMenu() { return m_pMenu; }
virtual void AddAction(QAction* pAction) { m_pMenu->insertAction(m_pLastAction, pAction); }
virtual T* GetTree() { return m_pTreeList; }
virtual QTreeView* GetView() { return m_pTreeList; }
virtual QAbstractItemModel* GetModel() { return m_pTreeList->model(); }
protected:
QVBoxLayout* m_pMainLayout;
T* m_pTreeList;
QAction* m_pLastAction;
};
#include "TreeWidgetEx.h"
#include "Finder.h"
class MISCHELPERS_EXPORT CPanelWidgetEx : public CPanelWidget<QTreeWidgetEx>
{
Q_OBJECT
public:
CPanelWidgetEx(QWidget *parent = 0) : CPanelWidget<QTreeWidgetEx>(parent)
{
m_pFinder = new CFinder(NULL, this, false);
m_pMainLayout->addWidget(m_pFinder);
QObject::connect(m_pFinder, SIGNAL(SetFilter(const QRegExp&, bool, int)), this, SLOT(SetFilter(const QRegExp&, bool, int)));
}
static void ApplyFilter(QTreeWidgetEx* pTree, QTreeWidgetItem* pItem, const QRegExp& Exp/*, bool bHighLight = false, int Col = -1*/)
{
for (int j = 0; j < pTree->columnCount(); j++)
pItem->setBackground(j, !Exp.isEmpty() && pItem->text(j).contains(Exp) ? Qt::yellow : Qt::white);
for (int i = 0; i < pItem->childCount(); i++)
{
ApplyFilter(pTree, pItem->child(i), Exp/*, bHighLight, Col*/);
}
}
static void ApplyFilter(QTreeWidgetEx* pTree, const QRegExp& Exp/*, bool bHighLight = false, int Col = -1*/)
{
for (int i = 0; i < pTree->topLevelItemCount(); i++)
ApplyFilter(pTree, pTree->topLevelItem(i), Exp/*, bHighLight, Col*/);
}
private slots:
void SetFilter(const QRegExp& Exp, bool bHighLight = false, int Col = -1) // -1 = any
{
ApplyFilter(m_pTreeList, Exp);
}
private:
CFinder* m_pFinder;
};
#include "TreeViewEx.h"
template <class T>
class CPanelViewImpl: public CPanelWidget<QTreeViewEx>
{
public:
CPanelViewImpl(T* pModel, QWidget *parent = 0) : CPanelWidget<QTreeViewEx>(parent)
{
m_pModel = pModel;
m_pSortProxy = new CSortFilterProxyModel(false, this);
m_pSortProxy->setSortRole(Qt::EditRole);
m_pSortProxy->setSourceModel(m_pModel);
m_pSortProxy->setDynamicSortFilter(true);
m_pTreeList->setModel(m_pSortProxy);
m_pTreeList->setSelectionMode(QAbstractItemView::ExtendedSelection);
#ifdef WIN32
QStyle* pStyle = QStyleFactory::create("windows");
m_pTreeList->setStyle(pStyle);
#endif
m_pTreeList->setSortingEnabled(true);
m_pTreeList->setContextMenuPolicy(Qt::CustomContextMenu);
connect(m_pTreeList, SIGNAL(customContextMenuRequested(const QPoint&)), this, SLOT(OnMenu(const QPoint &)));
m_pTreeList->setColumnReset(1);
//connect(m_pTreeList, SIGNAL(ResetColumns()), m_pTreeList, SLOT(OnResetColumns()));
//connect(m_pBoxTree, SIGNAL(ColumnChanged(int, bool)), this, SLOT(OnColumnsChanged()));
}
protected:
T* m_pModel;
QSortFilterProxyModel* m_pSortProxy;
};

View File

@ -0,0 +1,117 @@
#pragma once
#include "../mischelpers_global.h"
class MISCHELPERS_EXPORT CProgressDialog : public QMainWindow
{
Q_OBJECT
public:
CProgressDialog(const QString& Prompt, QWidget* parent = 0)
: QMainWindow(parent)
{
setWindowFlags(Qt::Tool);
m_pMainWidget = new QWidget();
m_pMainLayout = new QGridLayout(this);
m_pMainWidget->setLayout(m_pMainLayout);
this->setCentralWidget(m_pMainWidget);
m_pMessageLabel = new QLabel(Prompt);
m_pMessageLabel->setMinimumWidth(300);
m_pMessageLabel->setWordWrap(true);
m_pMainLayout->addWidget(m_pMessageLabel, 0, 0, 1, 1);
m_pProgressBar = new QProgressBar();
m_pProgressBar->setTextVisible(false);
m_pProgressBar->setMaximum(0);
m_pProgressBar->setMinimum(0);
m_pMainLayout->addWidget(m_pProgressBar, 1, 0, 1, 1);
m_pButtonBox = new QDialogButtonBox();
m_pButtonBox->setOrientation(Qt::Horizontal);
m_pButtonBox->setStandardButtons(QDialogButtonBox::Cancel);
m_pMainLayout->addWidget(m_pButtonBox, 2, 0, 1, 1);
setFixedSize(sizeHint());
connect(m_pButtonBox,SIGNAL(rejected()),this,SIGNAL(Cancel()));
m_TimerId = startTimer(1000);
m_CountDown = 0;
}
~CProgressDialog()
{
killTimer(m_TimerId);
}
signals:
void Cancel();
public slots:
void OnProgressMessage(const QString& Message, int Progress = -1)
{
if(!Message.isEmpty())
m_pMessageLabel->setText(Message);
if (Progress == -1)
{
if (m_pProgressBar->maximum() != 0)
m_pProgressBar->setMinimum(0);
}
else
{
if (m_pProgressBar->maximum() != 100)
m_pProgressBar->setMinimum(100);
m_pProgressBar->setValue(Progress);
}
}
void OnStatusMessage(const QString& Message, int Code = 0)
{
//if(Code == 0)
m_pMessageLabel->setText(Message);
//else // note: parent can't be set as this window may auto close
// QMessageBox::warning(NULL, this->windowTitle(), Message);
}
void OnFinished()
{
m_pButtonBox->button(QDialogButtonBox::Cancel)->setEnabled(false);
m_CountDown = 3;
}
protected:
void timerEvent(QTimerEvent *e)
{
if (e->timerId() != m_TimerId)
{
QMainWindow::timerEvent(e);
return;
}
if(m_CountDown != 0)
{
m_CountDown--;
m_pButtonBox->button(QDialogButtonBox::Cancel)->setText(tr("Close (%1)").arg(m_CountDown));
if (m_CountDown == 0)
close();
}
}
void closeEvent(QCloseEvent *e)
{
emit Cancel();
this->deleteLater();
}
int m_TimerId;
int m_CountDown;
QWidget* m_pMainWidget;
QGridLayout* m_pMainLayout;
QLabel* m_pMessageLabel;
QProgressBar* m_pProgressBar;
QDialogButtonBox* m_pButtonBox;
};

View File

@ -0,0 +1,113 @@
#include "stdafx.h"
#include "Settings.h"
//#include "qzlib.h"
#include "Common.h"
bool TestWriteRight(const QString& Path)
{
QFile TestFile(Path + "/~test-" + GetRand64Str() + ".tmp");
if(!TestFile.open(QFile::WriteOnly))
return false;
TestFile.close();
return TestFile.remove();
}
CSettings::CSettings(const QString& AppName, QMap<QString, SSetting> DefaultValues, QObject* qObject) : QObject(qObject)
{
m_ConfigDir = QCoreApplication::applicationDirPath();
if (!(m_bPortable = QFile::exists(m_ConfigDir + "/" + AppName + ".ini")))
{
QStringList dirs = QStandardPaths::standardLocations(QStandardPaths::GenericDataLocation);
if (dirs.isEmpty())
m_ConfigDir = QDir::homePath() + "/." + AppName;
else
m_ConfigDir = dirs.first() + "/" + AppName;
QDir().mkpath(m_ConfigDir);
}
m_pConf = new QSettings(m_ConfigDir + "/" + AppName + ".ini", QSettings::IniFormat, this);
m_pConf->sync();
m_DefaultValues = DefaultValues;
foreach (const QString& Key, m_DefaultValues.uniqueKeys())
{
const SSetting& Setting = m_DefaultValues[Key];
if(!m_pConf->contains(Key) || !Setting.Check(m_pConf->value(Key)))
{
if(Setting.IsBlob())
m_pConf->setValue(Key, Setting.Value.toByteArray().toBase64().replace("+","-").replace("/","_").replace("=",""));
else
m_pConf->setValue(Key, Setting.Value);
}
}
}
CSettings::~CSettings()
{
m_pConf->sync();
}
bool CSettings::SetValue(const QString &key, const QVariant &value)
{
QMutexLocker Locker(&m_Mutex);
if (!m_DefaultValues.isEmpty())
{
ASSERT(m_pConf->contains(key));
#ifndef _DEBUG
if (!m_DefaultValues[key].Check(value))
return false;
#endif
}
m_pConf->setValue(key, value);
m_ValueCache.clear();
return true;
}
QVariant CSettings::GetValue(const QString &key, const QVariant& preset)
{
QMutexLocker Locker(&m_Mutex);
ASSERT(m_DefaultValues.isEmpty() || m_pConf->contains(key));
return m_pConf->value(key, preset);
}
void CSettings::SetBlob(const QString& key, const QByteArray& value)
{
QString str;
//QByteArray data = Pack(value);
//if(data.size() < value.size())
// str = ":PackedArray:" + data.toBase64().replace("+","-").replace("/","_").replace("=","");
//else
str = ":ByteArray:" + value.toBase64().replace("+","-").replace("/","_").replace("=","");
SetValue(key, str);
}
QByteArray CSettings::GetBlob(const QString& key)
{
QByteArray value;
QByteArray str = GetValue(key).toByteArray();
if(str.left(11) == ":ByteArray:")
value = QByteArray::fromBase64(str.mid(11).replace("-","+").replace("_","/"));
//else if(str.left(13) == ":PackedArray:")
// value = Unpack(QByteArray::fromBase64(str.mid(13).replace("-","+").replace("_","/")));
return value;
}
const QStringList CSettings::ListKeys(const QString& Root)
{
QMutexLocker Locker(&m_Mutex);
QStringList Keys;
foreach(const QString& Key, m_pConf->allKeys())
{
QStringList Path = Key.split("/");
ASSERT(Path.count() == 2);
if(Path[0] == Root)
Keys.append(Path[1]);
}
return Keys;
}

View File

@ -0,0 +1,150 @@
#pragma once
#include <QSettings>
#include <QVariant>
#include <QMutex>
#include <QStringList>
#include "../mischelpers_global.h"
class MISCHELPERS_EXPORT CSettings: public QObject
{
Q_OBJECT
public:
struct SStrRef
{
SStrRef(const char* pRef)
: Ref(pRef) {}
bool operator < (const SStrRef& Other) const {return strcmp(Ref, Other.Ref) < 0;}
bool operator == (const SStrRef& Other) const {return strcmp(Ref, Other.Ref) == 0;}
operator QString() const {return QString(Ref);}
const char* Ref;
};
union SCacheVal
{
bool _Bool;
qint32 _Int;
quint32 _UInt;
quint64 _UInt64;
};
struct SSetting
{
SSetting(){
MinValue = 0;
MaxValue = 0;
}
SSetting(const QVariant& value){
Value = value;
MinValue = 0;
MaxValue = 0;
}
SSetting(qint64 value, qint64 minvalue = LLONG_MIN, qint64 maxvalue = LLONG_MAX) {
Value = value;
MinValue = minvalue;
MaxValue = maxvalue;
}
SSetting(const QString& value, const QStringList& values) {
Value = value;
MinValue = 0;
MaxValue = 0;
Values = values;
}
bool Check(const QVariant& value) const
{
if(MinValue != MaxValue)
{
if(!value.canConvert(QVariant::LongLong))
return false;
qint64 Test = value.toLongLong();
if(Test < MinValue || MinValue > MaxValue)
return false;
}
else if(!Values.isEmpty())
{
if(!value.canConvert(QVariant::String))
return false;
if(!Values.contains(value.toString()))
return false;
}
return true;
}
virtual bool IsBlob() const {return false;}
QVariant Value;
qint64 MinValue;
qint64 MaxValue;
QStringList Values;
};
struct SBlobSetting: SSetting
{
SBlobSetting(const QByteArray& value){
Value = value;
MinValue = 0;
MaxValue = 0;
}
virtual bool IsBlob() const {return true;}
};
CSettings(const QString& AppName, QMap<QString, SSetting> DefaultValues = QMap<QString, SSetting>(), QObject* qObject = NULL);
virtual ~CSettings();
bool SetValue(const QString& key, const QVariant& value);
QVariant GetValue(const QString& key, const QVariant& preset = QVariant());
void SetBlob(const QString& key, const QByteArray& value);
QByteArray GetBlob(const QString& key);
#define IMPL_CFG_CACHE_GET(x,y,z) \
x Get##y(const SStrRef& key, x def = 0) \
{ \
QMutexLocker Locker(&m_Mutex); \
QMap<SStrRef, SCacheVal>::Iterator I = m_ValueCache.find(key); \
if(I != m_ValueCache.end()) \
return I.value()._##y; \
Locker.unlock(); \
x val = GetValue(key, def).to##z(); \
Locker.relock(); \
SCacheVal entry; \
entry._##y = val; \
m_ValueCache.insert(key, entry); \
return val; \
}
IMPL_CFG_CACHE_GET(bool, Bool, Bool);
IMPL_CFG_CACHE_GET(qint32, Int, Int);
IMPL_CFG_CACHE_GET(quint32, UInt, UInt);
IMPL_CFG_CACHE_GET(quint64, UInt64, ULongLong);
#undef IMPL_CFG_CACHE_GET
const QString GetString(const QString& key, const QVariant& preset = QVariant()) {return GetValue(key, preset).toString();}
const QStringList GetStringList(const QString& key, const QVariant& preset = QVariant()) {return GetValue(key, preset).toStringList();}
const QStringList ListSettings() {QMutexLocker Locker(&m_Mutex); return m_pConf->allKeys();}
const QStringList ListGroupes() {QMutexLocker Locker(&m_Mutex); return m_pConf->childGroups();}
const QStringList ListKeys(const QString& Root);
const QString GetConfigDir() {QMutexLocker Locker(&m_Mutex); return m_ConfigDir;}
const bool IsPortable() {QMutexLocker Locker(&m_Mutex); return m_bPortable;}
protected:
QMutex m_Mutex;
QMap<QString, SSetting> m_DefaultValues;
QMap<SStrRef, SCacheVal>m_ValueCache;
QString m_ConfigDir;
bool m_bPortable;
QSettings* m_pConf;
};

View File

@ -0,0 +1,70 @@
#include "stdafx.h"
#include "SettingsWidgets.h"
#include "CheckableMessageBox.h"
///////////////////////////////////////////////////
// CPathEdit
CPathEdit::CPathEdit(bool bDirs, QWidget *parent)
: CTxtEdit(parent)
{
m_bDirs = bDirs;
QHBoxLayout* pLayout = new QHBoxLayout(this);
pLayout->setMargin(0);
m_pEdit = new QLineEdit(this);
connect(m_pEdit, SIGNAL(textChanged(const QString &)), this, SIGNAL(textChanged(const QString &)));
pLayout->addWidget(m_pEdit);
QPushButton* pButton = new QPushButton("...");
pButton->setMaximumWidth(25);
connect(pButton, SIGNAL(pressed()), this, SLOT(Browse()));
pLayout->addWidget(pButton);
}
void CPathEdit::Browse()
{
QString FilePath = m_bDirs
? QFileDialog::getExistingDirectory(this, tr("Select Directory"))
: QFileDialog::getOpenFileName(0, tr("Browse"), "", QString("Any File (*.*)"));
if(!FilePath.isEmpty())
SetText(FilePath);
}
///////////////////////////////////////////////////
// CProxyEdit
CProxyEdit::CProxyEdit(QWidget *parent)
: CTxtEdit(parent)
{
QHBoxLayout* pLayout = new QHBoxLayout(this);
pLayout->setMargin(0);
m_pType = new QComboBox();
m_pType->addItem(QString("No"));
m_pType->addItem(QString("http"));
m_pType->addItem(QString("socks5"));
connect(m_pType, SIGNAL(activated(int)), this, SLOT(OnType(int)));
pLayout->addWidget(m_pType);
m_pEdit = new QLineEdit(this);
connect(m_pEdit, SIGNAL(textChanged(const QString &)), this, SIGNAL(textChanged(const QString &)));
pLayout->addWidget(m_pEdit);
}
void CProxyEdit::SetText(const QString& Text)
{
QUrl Url(Text);
m_pType->setCurrentText(Url.scheme());
m_pEdit->setText(Text);
}
void CProxyEdit::OnType(int Index)
{
if(Index == 0)
m_pEdit->setEnabled(false);
else
{
m_pEdit->setEnabled(true);
m_pEdit->setText(m_pType->currentText() + "://");
}
}

View File

@ -0,0 +1,421 @@
#pragma once
#include "../mischelpers_global.h"
class MISCHELPERS_EXPORT CMultiLineEdit: public QPlainTextEdit
{
Q_OBJECT
public:
CMultiLineEdit(QWidget *parent = 0)
:QPlainTextEdit(parent) {}
void SetLines(const QStringList& Lines){
setPlainText(Lines.join("\r\n"));
}
QStringList GetLines(){
return toPlainText().split(QRegExp("\r?\n"));
}
};
///////////////////////////////////////////////////
//
class MISCHELPERS_EXPORT QNumEdit: public QLineEdit
{
Q_OBJECT
Q_PROPERTY(int Value READ GetValue WRITE SetValue)
public:
QNumEdit(QWidget *parent = 0) : QLineEdit(parent) {}
virtual void SetValue(qint64 Value) = 0;
virtual qint64 GetValue() = 0;
};
///////////////////////////////////////////////////
//
class MISCHELPERS_EXPORT CKbpsEdit: public QNumEdit
{
Q_OBJECT
public:
CKbpsEdit(qint64 Factor = 1024, QWidget *parent = 0)
:QNumEdit(parent) , m_Factor(Factor) {}
void SetValue(qint64 Value){
if(Value <= 0)
setText(tr("Unlimited"));
else
setText(QString::number(Value/m_Factor));
}
qint64 GetValue(){
int Value = text().toInt();
if(Value > 0)
return Value*m_Factor;
else
return -1; // Unlimited;
}
protected:
qint64 m_Factor;
};
///////////////////////////////////////////////////
//
class MISCHELPERS_EXPORT CFactorEdit: public QNumEdit
{
Q_OBJECT
public:
CFactorEdit(double Factor = 100.0, int Prec = 2, bool bEmpty = false, QWidget *parent = 0)
:QNumEdit(parent), m_Factor(Factor), m_Empty(bEmpty), m_Prec(Prec) {}
void SetValue(qint64 Value){
if(!Value && m_Empty)
setText("");
else
setText(QString::number(Value / m_Factor, 'f', m_Prec));
}
qint64 GetValue(){
return text().toDouble() * m_Factor;
}
protected:
double m_Factor;
bool m_Empty;
int m_Prec;
};
///////////////////////////////////////////////////
//
class MISCHELPERS_EXPORT CSpinBoxEx: public QSpinBox
{
Q_OBJECT
public:
CSpinBoxEx(quint64 Unit, QWidget *parent = 0)
:QSpinBox(parent) {
m_Unit = Unit;
setSingleStep(Unit);
setMaximum(INT_MAX);
}
protected:
virtual int valueFromText(const QString &text) const{
return text.toInt() * m_Unit;
}
virtual QString textFromValue(int val) const{
return QString::number(val / m_Unit);
}
quint64 m_Unit;
};
///////////////////////////////////////////////////
//
class MISCHELPERS_EXPORT CTxtEdit: public QWidget
{
Q_OBJECT
Q_PROPERTY(QString Data READ GetText WRITE SetText)
public:
CTxtEdit(QWidget *parent = 0) : QWidget(parent) {}
virtual void SetText(const QString& Text) = 0;
virtual QString GetText() = 0;
};
///////////////////////////////////////////////////
// CPathEdit
class MISCHELPERS_EXPORT CPathEdit: public CTxtEdit
{
Q_OBJECT
public:
CPathEdit(bool bDirs = false, QWidget *parent = 0);
QLineEdit* GetEdit() {return m_pEdit;}
void SetText(const QString& Text) {m_pEdit->setText(Text);}
QString GetText() {return m_pEdit->text();}
signals:
void textChanged(const QString& text);
private slots:
void Browse();
protected:
QLineEdit* m_pEdit;
bool m_bDirs;
};
///////////////////////////////////////////////////
// CProxyEdit
class MISCHELPERS_EXPORT CProxyEdit: public CTxtEdit
{
Q_OBJECT
public:
CProxyEdit(QWidget *parent = 0);
void SetText(const QString& Text);
QString GetText() {return m_pEdit->text();}
signals:
void textChanged(const QString& text);
private slots:
void OnType(int Index);
protected:
QComboBox* m_pType;
QLineEdit* m_pEdit;
};
///////////////////////////////////////////////////
//
class MISCHELPERS_EXPORT QComboBoxEx: public QComboBox
{
Q_OBJECT
Q_PROPERTY(QVariant Data READ GetData)
public:
QComboBoxEx(QWidget* pParent = 0) : QComboBox(pParent) {}
QVariant GetData() {return itemData(currentIndex());}
};
///////////////////////////////////////////////////
//
class MISCHELPERS_EXPORT QCheckBoxEx: public QCheckBox
{
Q_OBJECT
public:
QCheckBoxEx(const QString& Text, bool bSwap = true) : QCheckBox(Text)
{
m_bSwap = bSwap;
setTristate();
}
void SetState(int State)
{
if(m_bSwap)
{
switch(State)
{
case 0: State = Qt::PartiallyChecked; break;
case 1: State = Qt::Checked; break;
case 2: State = Qt::Unchecked; break;
}
}
setCheckState((Qt::CheckState)State);
}
int GetState()
{
int State = checkState();
if(m_bSwap)
{
switch(State)
{
case Qt::PartiallyChecked: State = 0; break;
case Qt::Checked: State = 1; break;
case Qt::Unchecked: State = 2; break;
}
}
return State;
}
protected:
bool m_bSwap;
};
///////////////////////////////////////////////////
//
class MISCHELPERS_EXPORT QSecretCheckBox: public QCheckBoxEx
{
Q_OBJECT
public:
QSecretCheckBox(const QString& Text) : QCheckBoxEx(Text, false)
{
setTristate(false);
}
protected:
void mouseDoubleClickEvent (QMouseEvent * e)
{
if(QApplication::keyboardModifiers() & Qt::ControlModifier)
setTristate();
}
};
///////////////////////////////////////////////////
// QSpinBoxEx
class MISCHELPERS_EXPORT QSpinBoxEx: public QSpinBox
{
public:
QSpinBoxEx(QWidget* parent, const QString& Default, const QString& Suffix = "", bool exponential = false) : QSpinBox(parent)
{
m_default = 1;
setRange(0, INT_MAX);
setSuffix(Suffix);
setSpecialValueText(Default + Suffix);
m_exponential = exponential;
}
void stepBy(int steps)
{
if(m_exponential)
{
int Value = value();
if(!Value)
{
Value = m_default;
if(Value <= 0)
Value = 1;
}
if(steps == 1)
setValue(Value*2);
else if(steps == -1)
setValue(Value/2);
else
QSpinBox::stepBy(steps);
}
else
QSpinBox::stepBy(steps);
}
void setDefault(int value) {m_default = value;}
protected:
int m_default;
bool m_exponential;
};
///////////////////////////////////////////////////
// CMenuAction & CActionWidget
class MISCHELPERS_EXPORT QMenu_: public QMenu { public: void initStyleOption_(QStyleOptionMenuItem *option, const QAction *action) const {QMenu::initStyleOption(option, action);} };
class MISCHELPERS_EXPORT CActionWidget: public QWidget
{
public:
CActionWidget(QWidget* parent = 0) : QWidget(parent) {}
void paintEvent(QPaintEvent* e)
{
QPainter p(this);
QMenu_ Menu;
QAction* action = new QAction(this);
QStyleOptionMenuItem opt;
Menu.initStyleOption_(&opt, action);
opt.menuRect = opt.rect = QRect(0, 0, 22, 22); // with this icons and text are drown properly
style()->drawControl(QStyle::CE_MenuItem, &opt, &p, this);
}
};
class MISCHELPERS_EXPORT CMenuAction: public QWidgetAction
{
public:
CMenuAction (QWidget* pControll, const QString& Title, QString IconFile = "") : QWidgetAction (pControll->parent())
{
QWidget* pWidget = new CActionWidget(pControll->parentWidget());
QHBoxLayout* pLayout = new QHBoxLayout();
pLayout->setMargin(0);
if(!IconFile.isEmpty())
{
QImage Image(IconFile);
QLabel* pIcon = new QLabel();
pIcon->setToolTip(Title);
pIcon->setPixmap(QPixmap::fromImage(Image).scaled(16,16, Qt::IgnoreAspectRatio, Qt::SmoothTransformation));
pLayout->addWidget(pIcon);
pLayout->insertSpacing(0, 3);
pLayout->insertSpacing(2, 6);
}
else
{
pLayout->addWidget(new QLabel(Title));
pLayout->insertSpacing(0, 32);
}
pLayout->addWidget(pControll);
pWidget->setLayout(pLayout);
setDefaultWidget(pWidget);
}
};
///////////////////////////////////////////////////
// QCheckComboBox
class MISCHELPERS_EXPORT QCheckComboBox : public QComboBox
{
Q_OBJECT
public:
QCheckComboBox()
{
view()->viewport()->installEventFilter(this);
}
virtual bool eventFilter(QObject *watched, QEvent *e)
{
switch (e->type())
{
case QEvent::MouseButtonPress:
break;
case QEvent::MouseButtonRelease:
QMouseEvent *m = static_cast<QMouseEvent *>(e);
// is check box rect pressed
if (m->localPos().x() < this->height())
{
QStandardItemModel *model_ = qobject_cast<QStandardItemModel *>(model());
Qt::CheckState state = model_->data(view()->currentIndex(), Qt::CheckStateRole).value<Qt::CheckState>();
if (state != Qt::Checked)
state = Qt::Checked;
else
state = Qt::Unchecked;
model_->setData(view()->currentIndex(), state, Qt::CheckStateRole);
emit checkStateChanged(view()->currentIndex().row(), state);
return true;
}
/*if (isVisible() && view()->rect().contains(m->pos()) && view()->currentIndex().isValid()
&& (view()->currentIndex().flags() & Qt::ItemIsEnabled)
&& (view()->currentIndex().flags() & Qt::ItemIsSelectable)) {
this->hidePopup();
this->setCurrentIndex(view()->currentIndex().row());
return true;
}*/
break;
}
return false;
}
signals:
void checkStateChanged(int Index, Qt::CheckState state);
};

View File

@ -0,0 +1,65 @@
#include "stdafx.h"
#include "SmartGridWidget.h"
#include <math.h>
CSmartGridWidget::CSmartGridWidget(QWidget* parent)
: QWidget(parent)
{
m_pMainLayout = new QGridLayout();
this->setLayout(m_pMainLayout);
m_pMainLayout->setMargin(1);
m_pMainLayout->setSpacing(2);
m_bReArangePending = false;
}
void CSmartGridWidget::SetBackground(const QColor& BackColor)
{
QPalette pal = palette();
pal.setColor(QPalette::Background, BackColor);
this->setAutoFillBackground(true);
this->setPalette(pal);
}
void CSmartGridWidget::AddWidget(QWidget* pWidget)
{
m_Widgets.append(pWidget);
if(!pWidget->parent())
pWidget->setParent(this);
if (!m_bReArangePending)
{
m_bReArangePending = true;
QTimer::singleShot(0, this, SLOT(ReArange()));
}
}
void CSmartGridWidget::ReArange()
{
m_bReArangePending = false;
int count = 0;
while (count < m_Widgets.size())
{
if (m_Widgets[count] == NULL)
m_Widgets.removeAt(count);
else
count++;
}
float columns = ceil(sqrt((float)count));
float rows = columns > 0 ? ceil(count / columns) : 0;
for (int row = 0; row < rows; row++)
{
for (int column = 0; column < columns; column++)
{
int index = row * columns + column;
if (index >= count)
break;
m_pMainLayout->addWidget(m_Widgets.at(index), row, column);
}
}
}

View File

@ -0,0 +1,30 @@
#pragma once
#include <qwidget.h>
#include "../mischelpers_global.h"
class MISCHELPERS_EXPORT CSmartGridWidget : public QWidget
{
Q_OBJECT
public:
CSmartGridWidget(QWidget* parent = NULL);
virtual ~CSmartGridWidget() {}
virtual void SetBackground(const QColor& BackColor);
virtual void AddWidget(QWidget* pWidget);
virtual int GetCount() { return m_Widgets.count(); }
virtual QWidget* GetWidget(int Index) { return m_Widgets.at(Index); }
public slots:
virtual void ReArange();
protected:
QGridLayout* m_pMainLayout;
QList<QPointer<QWidget>>m_Widgets;
bool m_bReArangePending;
};

View File

@ -0,0 +1,82 @@
#pragma once
#include "../mischelpers_global.h"
class MISCHELPERS_EXPORT CSortFilterProxyModel: public QSortFilterProxyModel
{
Q_OBJECT
public:
CSortFilterProxyModel(bool bAlternate, QObject* parrent = 0) : QSortFilterProxyModel(parrent)
{
m_bAlternate = bAlternate;
m_bHighLight = false;
}
bool filterAcceptsRow(int source_row, const QModelIndex & source_parent) const
{
if (m_bHighLight)
return true;
// allow the item to pass if any of the child items pass
if(!filterRegExp().isEmpty())
{
// get source-model index for current row
QModelIndex source_index = sourceModel()->index(source_row, 0, source_parent);
if(source_index.isValid())
{
// if any of children matches the filter, then current index matches the filter as well
int nb = sourceModel()->rowCount(source_index);
for(int i = 0; i < nb; i++)
{
if(filterAcceptsRow(i, source_index))
return true;
}
// check current index itself
return QSortFilterProxyModel::filterAcceptsRow(source_row, source_parent);
}
}
// default behavioure
return QSortFilterProxyModel::filterAcceptsRow(source_row, source_parent);
}
QVariant data(const QModelIndex &index, int role) const
{
QVariant Data = QSortFilterProxyModel::data(index, role);
if (role == Qt::BackgroundRole)
{
if (m_bHighLight)
{
if (!filterRegExp().isEmpty())
{
QString Key = QSortFilterProxyModel::data(index, filterRole()).toString();
if (Key.contains(filterRegExp()))
return QColor(Qt::yellow);
}
return QColor(Qt::white);
}
if (m_bAlternate && !Data.isValid())
{
if (0 == index.row() % 2)
return QColor(226, 237, 253);
else
return QColor(Qt::white);
}
}
return Data;
}
public slots:
void SetFilter(const QRegExp& Exp, bool bHighLight = false, int Col = -1) // -1 = any
{
m_bHighLight = bHighLight;
setFilterKeyColumn(Col);
setFilterRegExp(Exp);
}
protected:
bool m_bAlternate;
bool m_bHighLight;
};

View File

@ -0,0 +1,369 @@
#include "stdafx.h"
#include "SplitTreeView.h"
CSplitTreeView::CSplitTreeView(QAbstractItemModel* pModel, QWidget *parent) : QWidget(parent)
{
m_pModel = pModel;
m_pMainLayout = new QHBoxLayout();
m_pMainLayout->setMargin(0);
this->setLayout(m_pMainLayout);
m_pSplitter = new QSplitter();
m_pSplitter->setOrientation(Qt::Horizontal);
m_pMainLayout->addWidget(m_pSplitter);
#ifdef WIN32
QStyle* pStyle = QStyleFactory::create("windows");
#endif
m_LockSellection = 0;
// Tree
m_pTree = new QTreeView();
m_pOneModel = new COneColumnModel();
m_pOneModel->setSourceModel(m_pModel);
m_pTree->setModel(m_pOneModel);
//m_pTree->setModel(m_pSortProxy);
m_pTree->setSelectionMode(QAbstractItemView::ExtendedSelection);
#ifdef WIN32
m_pTree->setStyle(pStyle);
#endif
//m_pTree->setSortingEnabled(true);
m_pTree->setSortingEnabled(false);
m_pTree->setUniformRowHeights(true);
m_pTree->header()->setSortIndicatorShown(true);
m_pTree->header()->setSectionsClickable(true);
connect(m_pTree->header(), SIGNAL(sectionClicked(int)), this, SLOT(OnTreeCustomSortByColumn(int)));
m_pTree->setContextMenuPolicy(Qt::CustomContextMenu);
connect(m_pTree, SIGNAL(customContextMenuRequested( const QPoint& )), this, SIGNAL(MenuRequested(const QPoint &)));
m_pSplitter->addWidget(m_pTree);
//m_pSplitter->setCollapsible(0, false);
m_pSplitter->setStretchFactor(0, 0);
//
// List
// Note: It would be convinient to use QTreeViewEx here but qt does not scale well when there are too many columns
// hence we will add and remove columns at the model level directly.
// This way we can get out operational CPU usage to be quite comparable with TaskInfo na other advanced task managers
// Plus there are to many columns to cram them into one simple context menu :-)
//m_pList = new QTreeViewEx();
m_pList = new QTreeView();
m_pList->setModel(m_pModel);
m_pList->setSelectionMode(QAbstractItemView::ExtendedSelection);
#ifdef WIN32
m_pList->setStyle(pStyle);
#endif
m_pList->setSortingEnabled(true);
m_pList->setUniformRowHeights(true);
connect(m_pList->header(), SIGNAL(sectionClicked(int)), this, SLOT(OnListCustomSortByColumn(int)));
m_pList->setContextMenuPolicy(Qt::CustomContextMenu);
connect(m_pList, SIGNAL(customContextMenuRequested( const QPoint& )), this, SIGNAL(MenuRequested(const QPoint &)));
m_pSplitter->addWidget(m_pList);
m_pSplitter->setCollapsible(1, false);
m_pSplitter->setStretchFactor(1, 1);
//
connect(m_pSplitter, SIGNAL(splitterMoved(int,int)), this, SLOT(OnSplitterMoved(int,int)));
// Link selections
//m_pTree->setSelectionModel(m_pList->selectionModel()); // this works only when booth views share the same data model
connect(m_pTree->selectionModel(), SIGNAL(selectionChanged(QItemSelection,QItemSelection)), this, SLOT(OnTreeSelectionChanged(QItemSelection,QItemSelection)));
connect(m_pList->selectionModel(), SIGNAL(selectionChanged(QItemSelection,QItemSelection)), this, SLOT(OnListSelectionChanged(QItemSelection,QItemSelection)));
connect(m_pTree->selectionModel(), SIGNAL(currentChanged(QModelIndex,QModelIndex)), this, SLOT(OnTreeCurrentChanged(QModelIndex,QModelIndex)));
connect(m_pList->selectionModel(), SIGNAL(currentChanged(QModelIndex,QModelIndex)), this, SLOT(OnListCurrentChanged(QModelIndex,QModelIndex)));
m_bTreeEnabled = true;
m_pList->setColumnHidden(0, true);
// link expansion
connect(m_pTree, SIGNAL(expanded(const QModelIndex)), this, SLOT(OnExpandTree(const QModelIndex)));
connect(m_pTree, SIGNAL(collapsed(const QModelIndex)), this, SLOT(OnCollapseTree(const QModelIndex)));
//connect(m_pList, SIGNAL(expanded(const QModelIndex)), this, SLOT(expand(const QModelIndex)));
//connect(m_pList, SIGNAL(collapsed(const QModelIndex)), this, SLOT(collapse(const QModelIndex)));
// link scrollbars
m_pTree->setVerticalScrollBarPolicy(Qt::ScrollBarAlwaysOff);
m_pTree->setHorizontalScrollBarPolicy(Qt::ScrollBarAlwaysOn);
m_pList->setHorizontalScrollBarPolicy(Qt::ScrollBarAlwaysOn);
connect(m_pList->verticalScrollBar(), SIGNAL(valueChanged(int)), m_pTree->verticalScrollBar(), SLOT(setValue(int)));
connect(m_pTree->verticalScrollBar(), SIGNAL(valueChanged(int)), m_pList->verticalScrollBar(), SLOT(setValue(int)));
connect(m_pTree, SIGNAL(clicked(const QModelIndex&)), this, SLOT(OnClickedTree(const QModelIndex&)));
connect(m_pList, SIGNAL(clicked(const QModelIndex&)), this, SIGNAL(clicked(const QModelIndex&)));
connect(m_pTree, SIGNAL(doubleClicked(const QModelIndex&)), this, SLOT(OnDoubleClickedTree(const QModelIndex&)));
connect(m_pList, SIGNAL(doubleClicked(const QModelIndex&)), this, SIGNAL(doubleClicked(const QModelIndex&)));
//QTimer::singleShot(0, this, [this]() {
// emit TreeEnabled(m_bTreeEnabled);
//});
}
CSplitTreeView::~CSplitTreeView()
{
}
int CSplitTreeView::GetTreeWidth() const
{
QList<int> sizes = m_pSplitter->sizes();
return sizes[0];
}
void CSplitTreeView::SetTreeWidth(int Width)
{
QList<int> sizes = m_pSplitter->sizes();
int total = sizes[0] + sizes[1];
sizes[0] = Width;
sizes[1] = total - Width;
}
void CSplitTreeView::OnSplitterMoved(int pos, int index)
{
if (index != 1)
return;
//if ((pos > 0) == m_bTreeEnabled)
// return;
//m_bTreeEnabled = (pos > 0);
m_pList->setColumnHidden(0, pos > 0);
//emit TreeEnabled(m_bTreeEnabled);
}
void CSplitTreeView::OnExpandTree(const QModelIndex& index)
{
m_pList->expand(m_pOneModel->mapToSource(index));
}
void CSplitTreeView::OnCollapseTree(const QModelIndex& index)
{
m_pList->collapse(m_pOneModel->mapToSource(index));
}
void CSplitTreeView::OnClickedTree(const QModelIndex& Index)
{
emit clicked(m_pOneModel->mapToSource(Index));
}
void CSplitTreeView::OnDoubleClickedTree(const QModelIndex& Index)
{
emit doubleClicked(m_pOneModel->mapToSource(Index));
}
void CSplitTreeView::expand(const QModelIndex &index)
{
m_pTree->expand(m_pOneModel->mapFromSource(index));
}
void CSplitTreeView::collapse(const QModelIndex &index)
{
m_pTree->collapse(m_pOneModel->mapFromSource(index));
}
void CSplitTreeView::OnTreeSelectionChanged(const QItemSelection& Selected, const QItemSelection& Deselected)
{
if (m_LockSellection)
return;
m_LockSellection = 1;
QItemSelection SelectedItems;
foreach(const QModelIndex& Index, m_pTree->selectionModel()->selectedIndexes())
{
QModelIndex ModelIndex = m_pOneModel->mapToSource(Index);
QModelIndex ModelL = m_pModel->index(ModelIndex.row(), 0, ModelIndex.parent());
QModelIndex ModelR = m_pModel->index(ModelIndex.row(), m_pModel->columnCount()-1, ModelIndex.parent());
SelectedItems.append(QItemSelectionRange(ModelL, ModelR));
}
m_pList->selectionModel()->select(SelectedItems, QItemSelectionModel::ClearAndSelect);
/*
foreach(const QModelIndex& Index, Selected.indexes())
{
QModelIndex ModelIndex = m_pOneModel->mapToSource(Index);
QModelIndex ModelL = m_pModel->index(ModelIndex.row(), 0, ModelIndex.parent());
QModelIndex ModelR = m_pModel->index(ModelIndex.row(), m_pModel->columnCount()-1, ModelIndex.parent());
m_pList->selectionModel()->select(QItemSelection(ModelL, ModelR), QItemSelectionModel::Select);
}
foreach(const QModelIndex& Index, Deselected.indexes())
{
QModelIndex ModelIndex = m_pOneModel->mapToSource(Index);
QModelIndex ModelL = m_pModel->index(ModelIndex.row(), 0, ModelIndex.parent());
QModelIndex ModelR = m_pModel->index(ModelIndex.row(), m_pModel->columnCount()-1, ModelIndex.parent());
m_pList->selectionModel()->select(QItemSelection(ModelL, ModelR), QItemSelectionModel::Deselect);
}*/
m_LockSellection = 0;
}
void CSplitTreeView::OnListSelectionChanged(const QItemSelection& Selected, const QItemSelection& Deselected)
{
if (m_LockSellection != 2)
emit selectionChanged(Selected, Deselected);
if (m_LockSellection)
return;
m_LockSellection = 1;
QItemSelection SelectedItems;
foreach(const QModelIndex& Index, m_pList->selectionModel()->selectedIndexes())
{
QModelIndex ModelIndex = m_pOneModel->mapFromSource(Index);
if (ModelIndex.column() != 0)
continue;
QModelIndex Model = m_pOneModel->index(ModelIndex.row(), 0, ModelIndex.parent());
SelectedItems.append(QItemSelectionRange(Model));
}
m_pTree->selectionModel()->select(SelectedItems, QItemSelectionModel::ClearAndSelect);
/*foreach(const QModelIndex& Index, Selected.indexes())
{
QModelIndex ModelIndex = m_pOneModel->mapFromSource(Index);
if (ModelIndex.column() != 0)
continue;
m_pTree->selectionModel()->select(ModelIndex, QItemSelectionModel::Select);
}
foreach(const QModelIndex& Index, Deselected.indexes())
{
QModelIndex ModelIndex = m_pOneModel->mapFromSource(Index);
if (ModelIndex.column() != 0)
continue;
m_pTree->selectionModel()->select(ModelIndex, QItemSelectionModel::Deselect);
}*/
m_LockSellection = 0;
}
void CSplitTreeView::OnTreeCurrentChanged(const QModelIndex &current, const QModelIndex &previous)
{
if (m_LockSellection)
return;
m_LockSellection = 2;
int hPos = m_pList->horizontalScrollBar()->value(); // fix horizontalScrollBar position reset on selection
m_pList->selectionModel()->setCurrentIndex(m_pOneModel->mapToSource(current), QItemSelectionModel::SelectCurrent);
m_pList->horizontalScrollBar()->setValue(hPos);
m_LockSellection = 0;
emit currentChanged(m_pOneModel->mapToSource(current), m_pOneModel->mapToSource(previous));
}
void CSplitTreeView::OnListCurrentChanged(const QModelIndex &current, const QModelIndex &previous)
{
if (m_LockSellection)
return;
m_LockSellection = 2;
m_pTree->selectionModel()->setCurrentIndex(m_pOneModel->mapFromSource(current), QItemSelectionModel::SelectCurrent);
m_LockSellection = 0;
emit currentChanged(current, previous);
}
QModelIndexList CSplitTreeView::selectedRows() const
{
int Column = 0;
for (int i = 0; i < m_pModel->columnCount(); i++)
{
if (!m_pList->isColumnHidden(i))
{
Column = i;
break;
}
}
QModelIndexList IndexList;
foreach(const QModelIndex& Index, m_pList->selectionModel()->selectedIndexes())
{
if (Index.column() == Column)
IndexList.append(Index);
}
return IndexList;
}
void CSplitTreeView::SetTree(bool bSet)
{
m_bTreeEnabled = bSet;
emit TreeEnabled(m_bTreeEnabled);
}
void CSplitTreeView::OnTreeCustomSortByColumn(int column)
{
Qt::SortOrder order = m_pTree->header()->sortIndicatorOrder();
if (order == Qt::AscendingOrder)
SetTree(!m_bTreeEnabled);
m_pList->sortByColumn(column, order);
m_pTree->header()->setSortIndicatorShown(true);
}
void CSplitTreeView::OnListCustomSortByColumn(int column)
{
Qt::SortOrder order = m_pList->header()->sortIndicatorOrder();
if (column == 0)
SetTree(!m_bTreeEnabled);
else if (m_bTreeEnabled)
SetTree(false);
m_pTree->header()->setSortIndicatorShown(false);
}
static const qint32 CSplitTreeViewMagic = 'STVs';
QByteArray CSplitTreeView::saveState() const
{
int version = 1;
QByteArray data;
QDataStream stream(&data, QIODevice::WriteOnly);
stream << qint32(CSplitTreeViewMagic);
stream << qint32(version);
stream << m_pList->header()->saveState();
stream << m_pSplitter->saveState();
stream << m_bTreeEnabled;
return data;
}
bool CSplitTreeView::restoreState(const QByteArray &state)
{
int version = 1;
QByteArray sd = state;
QDataStream stream(&sd, QIODevice::ReadOnly);
qint32 marker;
stream >> marker;
qint32 v;
stream >> v;
if (marker != CSplitTreeViewMagic || v > version)
return false;
QByteArray header;
stream >> header;
m_pList->header()->restoreState(header);
QByteArray splitter;
stream >> splitter;
m_pSplitter->restoreState(splitter);
stream >> m_bTreeEnabled;
emit TreeEnabled(m_bTreeEnabled);
m_pTree->header()->setSortIndicatorShown(m_pList->header()->sortIndicatorSection() == 0);
QList<int> sizes = m_pSplitter->sizes();
for(int i=0; i < sizes.count(); i++)
OnSplitterMoved(sizes[i], i);
return true;
}

View File

@ -0,0 +1,116 @@
#pragma once
#include <qwidget.h>
#include "TreeViewEx.h"
#include "../mischelpers_global.h"
class MISCHELPERS_EXPORT COneColumnModel : public QIdentityProxyModel
{
Q_OBJECT
public:
COneColumnModel( QObject* parrent = 0) : QIdentityProxyModel(parrent) {}
int columnCount(const QModelIndex &parent = QModelIndex()) const { return 1; }
};
class MISCHELPERS_EXPORT CSplitTreeView : public QWidget
{
Q_OBJECT
public:
CSplitTreeView(QAbstractItemModel* pModel, QWidget *parent = 0);
virtual ~CSplitTreeView();
QTreeView* GetView() { return m_pList; }
QTreeView* GetTree() { return m_pTree; }
void SetTree(bool bSet);
bool IsTree() const { return m_bTreeEnabled; }
void SetTreeWidth(int Width);
int GetTreeWidth() const;
QModelIndex currentIndex() const { return m_pList->currentIndex(); }
QModelIndexList selectedRows() const;
QByteArray saveState() const;
bool restoreState(const QByteArray &state);
template<class T>
void StartUpdatingWidgets(T& OldMap, T& Map)
{
for(typename T::iterator I = Map.begin(); I != Map.end();)
{
if(I.value().first == NULL)
I = Map.erase(I);
else
{
OldMap.insert(I.key(), I.value());
I++;
}
}
}
template<class T>
void EndUpdatingWidgets(T& OldMap, T& Map)
{
for(typename T::iterator I = OldMap.begin(); I != OldMap.end(); I++)
{
Map.remove(I.key());
if(I.value().second.isValid())
m_pList->setIndexWidget(I.value().second, NULL);
}
}
signals:
void TreeEnabled(bool bEnabled);
void MenuRequested(const QPoint &);
void clicked(const QModelIndex& Index);
void doubleClicked(const QModelIndex& Index);
void currentChanged(const QModelIndex &current, const QModelIndex &previous);
void selectionChanged(const QItemSelection& selected, const QItemSelection& seselected);
public slots:
void hideColumn(int column) { m_pList->hideColumn(column); }
void showColumn(int column) { m_pList->showColumn(column); }
void expand(const QModelIndex &index);
void collapse(const QModelIndex &index);
void resizeColumnToContents(int column) { m_pList->resizeColumnToContents(column); }
void sortByColumn(int column) { m_pList->sortByColumn(column); }
void expandAll() { m_pTree->expandAll(); }
void collapseAll() { m_pTree->collapseAll(); }
void expandToDepth(int depth) { m_pTree->expandToDepth(depth); }
private slots:
void OnSplitterMoved(int pos, int index);
void OnClickedTree(const QModelIndex& Index);
void OnDoubleClickedTree(const QModelIndex& Index);
void OnExpandTree(const QModelIndex& index);
void OnCollapseTree(const QModelIndex& index);
void OnTreeSelectionChanged(const QItemSelection& Selected, const QItemSelection& Deselected);
void OnListSelectionChanged(const QItemSelection& Selected, const QItemSelection& Deselected);
void OnTreeCurrentChanged(const QModelIndex &current, const QModelIndex &previous);
void OnListCurrentChanged(const QModelIndex &current, const QModelIndex &previous);
void OnTreeCustomSortByColumn(int column);
void OnListCustomSortByColumn(int column);
private:
QHBoxLayout* m_pMainLayout;
bool m_bTreeEnabled;
QSplitter* m_pSplitter;
QTreeView* m_pTree;
QTreeView* m_pList;
QAbstractItemModel* m_pModel;
COneColumnModel* m_pOneModel;
int m_LockSellection;
};

View File

@ -0,0 +1,76 @@
#include "stdafx.h"
#include "TabPanel.h"
CTabPanel::CTabPanel(QWidget* parent)
: QWidget(parent)
{
m_pMainLayout = new QVBoxLayout();
m_pMainLayout->setMargin(0);
this->setLayout(m_pMainLayout);
#ifdef USE_QEXTWIDGETS
m_pTabs = new QTabWidgetEx();
m_pTabs->setMultiRow(true);
#else
m_pTabs = new QTabWidget();
#endif
m_pMainLayout->addWidget(m_pTabs);
}
CTabPanel::~CTabPanel()
{
}
void CTabPanel::ShowTab(int Index, bool bShow)
{
if (Index >= m_AllTabs.size())
return;
m_AllTabs[Index].bVisible = bShow;
int ActiveTab = 0;
QStringList VisibleTabs;
SaveTabs(ActiveTab, VisibleTabs);
RebuildTabs(ActiveTab, VisibleTabs);
}
void CTabPanel::AddTab(QWidget* pWidget, const QString& Name)
{
STab Tab{Name, pWidget, true};
m_AllTabs.append(Tab);
m_pTabs->addTab(Tab.pWidget, Tab.Name);
}
void CTabPanel::SaveTabs(int& ActiveTab, QStringList& VisibleTabs)
{
ActiveTab = 0;
VisibleTabs.clear();
for(int i=0; i < m_AllTabs.size(); i++)
{
STab& Tab = m_AllTabs[i];
VisibleTabs.append(QString::number(Tab.bVisible));
if (m_pTabs->currentWidget() == Tab.pWidget)
ActiveTab = i;
}
}
void CTabPanel::RebuildTabs(const int ActiveTab, const QStringList& VisibleTabs)
{
m_pTabs->clear();
for(int i=0; i < m_AllTabs.size(); i++)
{
STab& Tab = m_AllTabs[i];
if (VisibleTabs.size() <= i || VisibleTabs[i].toInt() != 0)
{
Tab.bVisible = true;
m_pTabs->addTab(Tab.pWidget, Tab.Name);
if (i == ActiveTab)
m_pTabs->setCurrentWidget(Tab.pWidget);
}
}
}

View File

@ -0,0 +1,44 @@
#pragma once
#include <qwidget.h>
#include "Settings.h"
#ifdef USE_QEXTWIDGETS
#include "../../qextwidgets/qtabwidgetex.h"
#endif
#include "../mischelpers_global.h"
class MISCHELPERS_EXPORT CTabPanel : public QWidget
{
Q_OBJECT
public:
CTabPanel(QWidget* parent = 0);
virtual ~CTabPanel();
virtual int GetTabCount() { return m_AllTabs.size(); }
virtual QString GetTabLabel(int Index) { if (Index >= m_AllTabs.size()) return ""; return m_AllTabs[Index].Name; }
virtual void ShowTab(int Index, bool bShow);
virtual bool IsTabVisible(int Index) { if (Index >= m_AllTabs.size()) return ""; return m_AllTabs[Index].bVisible; }
protected:
virtual void InitializeTabs() = 0;
virtual void AddTab(QWidget* pWidget, const QString& Name);
virtual void RebuildTabs(const int ActiveTab, const QStringList& VisibleTabs);
virtual void SaveTabs(int& ActiveTab, QStringList& VisibleTabs);
QVBoxLayout* m_pMainLayout;
#ifdef USE_QEXTWIDGETS
QTabWidgetEx* m_pTabs;
#else
QTabWidget* m_pTabs;
#endif
struct STab
{
QString Name;
QWidget* pWidget;
bool bVisible;
};
QVector<STab> m_AllTabs;
};

View File

@ -0,0 +1,502 @@
#include "stdafx.h"
#include "TreeItemModel.h"
#define FIRST_COLUMN 0
bool CTreeItemModel::m_DarkMode = false;
CTreeItemModel::CTreeItemModel(QObject *parent)
: QAbstractItemModelEx(parent)
{
m_bTree = true;
m_bUseIcons = false;
m_Root = NULL;
}
CTreeItemModel::~CTreeItemModel()
{
delete m_Root;
}
CSimpleTreeModel::CSimpleTreeModel(QObject *parent)
: CTreeItemModel(parent)
{
m_Root = MkNode(QVariant());
}
QList<QVariant> CSimpleTreeModel::MakePath(const QVariantMap& Cur, const QMap<QVariant, QVariantMap>& List)
{
QVariant ParentID = Cur["ParentID"];
QVariantMap Parent = List.value(ParentID);
QList<QVariant> Path;
if (!Parent.isEmpty())
{
Path = MakePath(Parent, List);
Path.append(ParentID);
}
return Path;
}
bool CSimpleTreeModel::TestPath(const QList<QVariant>& Path, const QVariantMap& Cur, const QMap<QVariant, QVariantMap>& List, int Index)
{
QVariant ParentID = Cur["ParentID"];
QVariantMap Parent = List.value(ParentID);
if (!Parent.isEmpty())
{
if(Index >= Path.size() || Path[Path.size() - Index - 1] != ParentID)
return false;
return TestPath(Path, Parent, List, Index + 1);
}
return Path.size() == Index;
}
void CSimpleTreeModel::Sync(const QMap<QVariant, QVariantMap>& List)
{
QMap<QList<QVariant>, QList<STreeNode*> > New;
QHash<QVariant, STreeNode*> Old = m_Map;
foreach (const QVariantMap& Cur, List)
{
QVariant ID = Cur["ID"];
QModelIndex Index;
STreeNode* pNode = static_cast<STreeNode*>(Old.value(ID));
if(!pNode || (m_bTree ? !TestPath(pNode->Path, Cur, List) : !pNode->Path.isEmpty()))
{
pNode = static_cast<STreeNode*>(MkNode(ID));
pNode->Values.resize(columnCount());
if(m_bTree)
pNode->Path = MakePath(Cur, List);
pNode->IsBold = Cur["IsBold"].toBool();
pNode->Icon = Cur["Icon"];
New[pNode->Path].append(pNode);
}
else
{
Old[ID] = NULL;
Index = Find(m_Root, pNode);
}
//if(Index.isValid()) // this is to slow, be more precise
// emit dataChanged(createIndex(Index.row(), 0, pNode), createIndex(Index.row(), columnCount()-1, pNode));
int Col = 0;
bool State = false;
bool Changed = false;
QVariantMap Values = Cur["Values"].toMap();
for(int section = FIRST_COLUMN; section < columnCount(); section++)
{
if (!m_Columns.contains(section))
continue; // ignore columns which are hidden
QVariant Value = Values[QString::number(section)];
STreeNode::SValue& ColValue = pNode->Values[section];
if (ColValue.Raw != Value)
{
Changed = true;
ColValue.Raw = Value;
//ColValue.Formated =
}
if(State != Changed)
{
if(State && Index.isValid())
emit dataChanged(createIndex(Index.row(), Col, pNode), createIndex(Index.row(), section-1, pNode));
State = Changed;
Col = section;
}
Changed = false;
}
if(State && Index.isValid())
emit dataChanged(createIndex(Index.row(), Col, pNode), createIndex(Index.row(), columnCount()-1, pNode));
}
CTreeItemModel::Sync(New, Old);
}
void CTreeItemModel::Sync(QMap<QList<QVariant>, QList<STreeNode*> >& New, QHash<QVariant, STreeNode*>& Old)
{
Purge(m_Root, QModelIndex(), Old);
if(!New.isEmpty())
{
emit layoutAboutToBeChanged();
//foreach(const QString& Path, New.uniqueKeys())
for(QMap<QList<QVariant>, QList<STreeNode*> >::const_iterator I = New.begin(); I != New.end(); I++)
Fill(m_Root, QModelIndex(), I.key(), 0, I.value(), I.key());
emit layoutChanged();
}
emit Updated();
}
/*void CTreeItemModel::CountItems()
{
CountItems(m_Root);
}
int CTreeItemModel::CountItems(STreeNode* pRoot)
{
if(pRoot->Children.isEmpty())
return 1;
int Counter = 0;
foreach(STreeNode* pChild, pRoot->Children)
Counter += CountItems(pChild);
//pRoot->AllChildren = Counter;
return Counter;
}*/
void CTreeItemModel::Purge(STreeNode* pParent, const QModelIndex &parent, QHash<QVariant, STreeNode*> &Old)
{
int Removed = 0;
int Begin = -1;
int End = -1;
for(int i = pParent->Children.count()-1; i >= -1; i--)
{
STreeNode* pNode = i >= 0 ? pNode = pParent->Children[i] : NULL;
if(pNode)
Purge(pNode, index(i, 0, parent), Old);
bool bRemove = false;
if(pNode && (pNode->ID.isNull() || (bRemove = Old.value(pNode->ID) != NULL)) && pNode->Children.isEmpty()) // remove it
{
//m_Map.remove(pNode->ID, pNode);
m_Map.remove(pNode->ID);
if(End == -1)
End = i;
}
else // keep it
{
if(bRemove)
{
ASSERT(!pNode->Children.isEmpty()); // we wanted to remove it but we have to keep it
//m_Map.remove(pNode->ID, pNode);
m_Map.remove(pNode->ID);
pNode->ID = QVariant();
pNode->Icon.clear();
}
if(End != -1) // remove whats to be removed at once
{
Begin = i + 1;
beginRemoveRows(parent, Begin, End);
//ASSERT(pParent->Children.count() > End);
for(int j = End; j >= Begin; j--)
{
pNode = pParent->Children.takeAt(j);
delete pNode;
Removed++;
}
endRemoveRows();
End = -1;
Begin = -1;
}
}
}
if(Removed > 0)
{
pParent->Aux.clear();
for (int i = pParent->Children.count() - 1; i >= 0; i--)
{
pParent->Children[i]->Row = i;
pParent->Aux.insert(pParent->Children[i]->ID, i);
}
}
}
void CTreeItemModel::Fill(STreeNode* pParent, const QModelIndex &parent, const QList<QVariant>& Paths, int PathsIndex, const QList<STreeNode*>& New, const QList<QVariant>& Path)
{
if(Paths.size() > PathsIndex)
{
QVariant CurPath = Paths.at(PathsIndex);
STreeNode* pNode;
int i = pParent->Aux.value(CurPath, -1);
if(i != -1)
pNode = pParent->Children[i];
else
{
i = 0;
pNode = MkNode(QVariant());
pNode->Parent = pParent;
pNode->Values.resize(columnCount());
//int Count = pParent->Children.count();
//beginInsertRows(parent, Count, Count);
pParent->Aux.insert(pNode->ID, pParent->Children.size());
pNode->Row = pParent->Children.size();
pParent->Children.append(pNode);
//endInsertRows();
}
Fill(pNode, index(i, 0, parent), Paths, PathsIndex + 1, New, Path);
}
else
{
for(QList<STreeNode*>::const_iterator I = New.begin(); I != New.end(); I++)
{
STreeNode* pNode = *I;
ASSERT(pNode);
//ASSERT(!m_Map.contains(pNode->ID));
m_Map.insert(pNode->ID, pNode);
pNode->Parent = pParent;
//int Count = pParent->Children.count();
//beginInsertRows(parent, Count, Count);
pParent->Aux.insert(pNode->ID, pParent->Children.size());
pNode->Row = pParent->Children.size();
pParent->Children.append(pNode);
//endInsertRows();
}
}
}
QModelIndex CTreeItemModel::FindIndex(const QVariant& ID)
{
if(STreeNode* pNode = m_Map.value(ID))
return Find(m_Root, pNode);
return QModelIndex();
}
QModelIndex CTreeItemModel::Find(STreeNode* pParent, STreeNode* pNode)
{
// ''find''
ASSERT(pNode->Parent->Children[pNode->Row] == pNode);
return createIndex(pNode->Row, FIRST_COLUMN, pNode);
/*
int count = pParent->Children.count();
for(int i=0; i < count; i++)
{
if (pParent->Children[i] == pNode)
{
ASSERT(i == pNode->Row);
return createIndex(i, FIRST_COLUMN, pNode);
}
QModelIndex Index = Find(pParent->Children[i], pNode);
if(Index.isValid())
return Index;
}
return QModelIndex();
*/
}
void CTreeItemModel::Clear()
{
QHash<QVariant, STreeNode*> Old = m_Map;
//beginResetModel();
Purge(m_Root, QModelIndex(), Old);
//endResetModel();
ASSERT(m_Map.isEmpty());
}
void CTreeItemModel::RemoveIndex(const QModelIndex &index)
{
if (!index.isValid())
return;
STreeNode* pNode = static_cast<STreeNode*>(index.internalPointer());
ASSERT(pNode);
QHash<QVariant, STreeNode*> Old;
Old[pNode->ID] = pNode;
Purge(m_Root, QModelIndex(), Old);
}
QVariant CTreeItemModel::data(const QModelIndex &index, int role) const
{
return Data(index, role, index.column());
}
bool CTreeItemModel::setData(const QModelIndex &index, const QVariant &value, int role)
{
if(index.column() == FIRST_COLUMN && role == Qt::CheckStateRole)
{
STreeNode* pNode = static_cast<STreeNode*>(index.internalPointer());
ASSERT(pNode);
emit CheckChanged(pNode->ID, value.toInt() != Qt::Unchecked);
return true;
}
return false;
}
QVariant CTreeItemModel::Data(const QModelIndex &index, int role, int section) const
{
if (!index.isValid())
return QVariant();
//if(role == Qt::SizeHintRole)
// return QSize(64,16); // for fixing height
STreeNode* pNode = static_cast<STreeNode*>(index.internalPointer());
ASSERT(pNode);
if (pNode->Values.size() <= section)
return QVariant();
return NodeData(pNode, role, section);
}
QVariant CTreeItemModel::NodeData(STreeNode* pNode, int role, int section) const
{
switch(role)
{
case Qt::DisplayRole:
{
STreeNode::SValue& Value = pNode->Values[section];
return Value.Formated.isValid() ? Value.Formated : Value.Raw;
}
case Qt::EditRole: // sort role
{
STreeNode::SValue& value = pNode->Values[section];
return value.SortKey.isValid() ? value.SortKey : value.Raw;
}
case Qt::ToolTipRole:
{
QString ToolTip;
emit ToolTipCallback(pNode->ID, ToolTip);
if(!ToolTip.isNull())
return ToolTip;
break;
}
case Qt::DecorationRole:
{
if (m_bUseIcons && section == FIRST_COLUMN)
return pNode->Icon.isValid() ? pNode->Icon : GetDefaultIcon();
break;
}
case Qt::FontRole:
{
if (section == FIRST_COLUMN && pNode->IsBold)
{
QFont fnt;
fnt.setBold(true);
return fnt;
}
break;
}
case Qt::BackgroundRole:
{
if(!m_DarkMode)
return pNode->Color.isValid() ? pNode->Color : QVariant();
break;
}
case Qt::ForegroundRole:
{
if(m_DarkMode)
return pNode->Color.isValid() ? pNode->Color : QVariant();
else if (pNode->IsGray)
{
QColor Color = Qt::darkGray;
return QBrush(Color);
}
break;
}
case Qt::CheckStateRole:
{
/*if(section == eModule)
{
if(pNode->...)
return Qt::Unchecked;
else
return Qt::Checked;
}*/
break;
}
case Qt::UserRole:
{
switch(section)
{
case FIRST_COLUMN: return pNode->ID;
}
break;
}
}
return QVariant();
}
Qt::ItemFlags CTreeItemModel::flags(const QModelIndex &index) const
{
if (!index.isValid())
return 0;
if(index.column() == 0)
return Qt::ItemIsEnabled | Qt::ItemIsSelectable | Qt::ItemIsUserCheckable;
return Qt::ItemIsEnabled | Qt::ItemIsSelectable;
}
QModelIndex CTreeItemModel::index(int row, int column, const QModelIndex &parent) const
{
if (!hasIndex(row, column, parent))
return QModelIndex();
STreeNode* pParent;
if (!parent.isValid())
pParent = m_Root;
else
pParent = static_cast<STreeNode*>(parent.internalPointer());
if(STreeNode* pNode = pParent->Children.count() > row ? pParent->Children[row] : NULL)
return createIndex(row, column, pNode);
return QModelIndex();
}
QModelIndex CTreeItemModel::parent(const QModelIndex &index) const
{
if (!index.isValid())
return QModelIndex();
STreeNode* pNode = static_cast<STreeNode*>(index.internalPointer());
ASSERT(pNode->Parent);
STreeNode* pParent = pNode->Parent;
if (pParent == m_Root)
return QModelIndex();
int row = 0;
if(pParent->Parent)
row = pParent->Parent->Children.indexOf(pParent);
return createIndex(row, 0, pParent);
}
int CTreeItemModel::rowCount(const QModelIndex &parent) const
{
if (parent.column() > 0)
return 0;
STreeNode* pNode;
if (!parent.isValid())
pNode = m_Root;
else
pNode = static_cast<STreeNode*>(parent.internalPointer());
return pNode->Children.count();
}
int CSimpleTreeModel::columnCount(const QModelIndex &parent) const
{
return m_Headers.count();
}
QVariant CSimpleTreeModel::headerData(int section, Qt::Orientation orientation, int role) const
{
if (orientation == Qt::Horizontal && role == Qt::DisplayRole)
{
if (section < m_Headers.size())
return m_Headers.at(section);
}
return QVariant();
}

View File

@ -0,0 +1,123 @@
#pragma once
#include "TreeViewEx.h"
#include "../mischelpers_global.h"
class MISCHELPERS_EXPORT CTreeItemModel : public QAbstractItemModelEx
{
Q_OBJECT
public:
CTreeItemModel(QObject *parent = 0);
virtual ~CTreeItemModel();
void SetTree(bool bTree) { m_bTree = bTree; }
bool IsTree() const { return m_bTree; }
void SetUseIcons(bool bUseIcons) { m_bUseIcons = bUseIcons; }
static void SetDarkMode(bool bDark) { m_DarkMode = bDark;}
//void CountItems();
QModelIndex FindIndex(const QVariant& ID);
void RemoveIndex(const QModelIndex &index);
QVariant Data(const QModelIndex &index, int role, int section) const;
// derived functions
virtual QVariant data(const QModelIndex &index, int role) const;
virtual bool setData(const QModelIndex &index, const QVariant &value, int role);
virtual Qt::ItemFlags flags(const QModelIndex &index) const;
virtual QModelIndex index(int row, int column, const QModelIndex &parent = QModelIndex()) const;
virtual QModelIndex parent(const QModelIndex &index) const;
virtual int rowCount(const QModelIndex &parent = QModelIndex()) const;
virtual int columnCount(const QModelIndex &parent = QModelIndex()) const = 0;
virtual QVariant headerData(int section, Qt::Orientation orientation, int role = Qt::DisplayRole) const = 0;
public slots:
void Clear();
signals:
void CheckChanged(const QVariant& ID, bool State);
void ToolTipCallback(const QVariant& ID, QString& ToolTip) const;
void Updated();
protected:
struct STreeNode
{
STreeNode(const QVariant& Id){
ID = Id;
Parent = NULL;
Row = 0;
//AllChildren = 0;
IsBold = false;
IsGray = false;
}
virtual ~STreeNode(){
foreach(STreeNode* pNode, Children)
delete pNode;
}
QVariant ID;
STreeNode* Parent;
int Row;
QList<QVariant> Path;
QList<STreeNode*> Children;
//int AllChildren;
QMap<QVariant, int> Aux;
QVariant Icon;
bool IsBold;
bool IsGray;
QColor Color;
struct SValue
{
QVariant Raw;
QVariant SortKey;
QVariant Formated;
};
QVector<SValue> Values;
};
virtual QVariant NodeData(STreeNode* pNode, int role, int section) const;
virtual STreeNode* MkNode(const QVariant& Id) = 0; // { return new STreeNode(Id); }
void Sync(QMap<QList<QVariant>, QList<STreeNode*> >& New, QHash<QVariant, STreeNode*>& Old);
void Purge(STreeNode* pParent, const QModelIndex &parent, QHash<QVariant, STreeNode*>& Old);
void Fill(STreeNode* pParent, const QModelIndex &parent, const QList<QVariant>& Paths, int PathsIndex, const QList<STreeNode*>& New, const QList<QVariant>& Path);
QModelIndex Find(STreeNode* pParent, STreeNode* pNode);
//int CountItems(STreeNode* pRoot);
virtual QVariant GetDefaultIcon() const { return QVariant(); }
STreeNode* m_Root;
QHash<QVariant, STreeNode*> m_Map;
bool m_bTree;
bool m_bUseIcons;
static bool m_DarkMode;
};
class MISCHELPERS_EXPORT CSimpleTreeModel : public CTreeItemModel
{
Q_OBJECT
public:
CSimpleTreeModel(QObject *parent = 0);
void Sync(const QMap<QVariant, QVariantMap>& List);
void setHeaderLabels(const QStringList& Columns) { m_Headers = Columns; }
virtual int columnCount(const QModelIndex &parent = QModelIndex()) const;
virtual QVariant headerData(int section, Qt::Orientation orientation, int role = Qt::DisplayRole) const;
protected:
virtual STreeNode* MkNode(const QVariant& Id) { return new STreeNode(Id); }
QList<QVariant> MakePath(const QVariantMap& Cur, const QMap<QVariant, QVariantMap>& List);
bool TestPath(const QList<QVariant>& Path, const QVariantMap& Cur, const QMap<QVariant, QVariantMap>& List, int Index = 0);
QStringList m_Headers;
};

View File

@ -0,0 +1,346 @@
#pragma once
#include <QStyledItemDelegate>
__inline uint qHash( const QVariant & var )
{
if ( !var.isValid() || var.isNull() )
//return -1;
Q_ASSERT(0);
switch ( var.type() )
{
case QVariant::Int:
return qHash( var.toInt() );
break;
case QVariant::UInt:
return qHash( var.toUInt() );
break;
case QVariant::Bool:
return qHash( var.toUInt() );
break;
case QVariant::Double:
return qHash( var.toUInt() );
break;
case QVariant::LongLong:
return qHash( var.toLongLong() );
break;
case QVariant::ULongLong:
return qHash( var.toULongLong() );
break;
case QVariant::String:
return qHash( var.toString() );
break;
case QVariant::Char:
return qHash( var.toChar() );
break;
case QVariant::StringList:
return qHash( var.toString() );
break;
case QVariant::ByteArray:
return qHash( var.toByteArray() );
break;
case QVariant::Date:
case QVariant::Time:
case QVariant::DateTime:
case QVariant::Url:
case QVariant::Locale:
case QVariant::RegExp:
return qHash( var.toString() );
break;
case QVariant::Map:
case QVariant::List:
case QVariant::BitArray:
case QVariant::Size:
case QVariant::SizeF:
case QVariant::Rect:
case QVariant::LineF:
case QVariant::Line:
case QVariant::RectF:
case QVariant::Point:
case QVariant::PointF:
// not supported yet
break;
case QVariant::UserType:
case QVariant::Invalid:
default:
return -1;
}
// could not generate a hash for the given variant
return -1;
}
#include "../mischelpers_global.h"
class MISCHELPERS_EXPORT QAbstractItemModelEx : public QAbstractItemModel
{
Q_OBJECT
public:
QAbstractItemModelEx(QObject *parent = 0) : QAbstractItemModel(parent) {}
virtual ~QAbstractItemModelEx() {}
bool IsColumnEnabled(int column)
{
return m_Columns.contains(column);
}
void SetColumnEnabled(int column, bool set)
{
if (!set)
m_Columns.remove(column);
else
m_Columns.insert(column);
}
protected:
QSet<int> m_Columns;
};
class MISCHELPERS_EXPORT QTreeViewEx: public QTreeView
{
Q_OBJECT
public:
QTreeViewEx(QWidget *parent = 0) : QTreeView(parent)
{
setUniformRowHeights(true);
m_ColumnReset = 1;
header()->setContextMenuPolicy(Qt::CustomContextMenu);
connect(header(), SIGNAL(customContextMenuRequested( const QPoint& )), this, SLOT(OnMenuRequested(const QPoint &)));
m_pMenu = new QMenu(this);
}
void setColumnReset(int iMode)
{
m_ColumnReset = iMode;
}
void setColumnFixed(int column, bool fixed)
{
if (fixed)
m_FixedColumns.insert(column);
else
m_FixedColumns.remove(column);
}
bool isColumnFixed(int column) const
{
return m_FixedColumns.contains(column);
}
QModelIndexList selectedRows() const
{
int Column = 0;
QAbstractItemModel* pModel = model();
for (int i = 0; i < pModel->columnCount(); i++)
{
if (!isColumnHidden(i))
{
Column = i;
break;
}
}
QModelIndexList IndexList;
foreach(const QModelIndex& Index, selectedIndexes())
{
if (Index.column() == Column)
IndexList.append(Index);
}
return IndexList;
}
template<class T>
void StartUpdatingWidgets(T& OldMap, T& Map)
{
for(typename T::iterator I = Map.begin(); I != Map.end();)
{
if(I.value().first == NULL)
I = Map.erase(I);
else
{
OldMap.insert(I.key(), I.value());
I++;
}
}
}
template<class T>
void EndUpdatingWidgets(T& OldMap, T& Map)
{
for(typename T::iterator I = OldMap.begin(); I != OldMap.end(); I++)
{
Map.remove(I.key());
if(I.value().second.isValid())
setIndexWidget(I.value().second, NULL);
}
}
bool restoreState(const QByteArray &state)
{
bool bRet = header()->restoreState(state);
SyncColumnsWithModel();
return bRet;
}
QByteArray saveState() const
{
return header()->saveState();
}
QAbstractItemModelEx* modelEx() const
{
QAbstractItemModelEx* pModel = qobject_cast<QAbstractItemModelEx*>(model());
if (!pModel)
{
QSortFilterProxyModel* pProxyModel = qobject_cast<QSortFilterProxyModel*>(model());
if(pProxyModel)
pModel = qobject_cast<QAbstractItemModelEx*>(pProxyModel->sourceModel());
}
return pModel;
}
void SetColumnHidden(int column, bool hide, bool fixed = false)
{
if (!fixed && isColumnFixed(column))
return; // can not change fixed columns
setColumnHidden(column, hide);
if(QAbstractItemModelEx* pModel = modelEx())
pModel->SetColumnEnabled(column, !hide);
if (fixed)
setColumnFixed(column, true);
emit ColumnChanged(column, !hide);
}
signals:
void ColumnChanged(int column, bool visible);
void ResetColumns();
public slots:
void SyncColumnsWithModel()
{
if(QAbstractItemModelEx* pModel = modelEx())
{
for (int i = 0; i < pModel->columnCount(); i++)
pModel->SetColumnEnabled(i, !isColumnHidden(i));
}
}
void OnResetColumns()
{
QAbstractItemModel* pModel = model();
for (int i = 0; i < pModel->columnCount(); i++)
SetColumnHidden(i, false);
}
private slots:
void OnMenuRequested(const QPoint &point)
{
QAbstractItemModel* pModel = model();
if(m_Columns.isEmpty())
{
for(int i=0; i < pModel->columnCount(); i++)
{
QString Label = pModel->headerData(i, Qt::Horizontal, Qt::DisplayRole).toString();
if(Label.isEmpty() || m_FixedColumns.contains(i))
continue;
QAction* pAction = new QAction(Label, m_pMenu);
pAction->setCheckable(true);
pAction->setChecked(!isColumnHidden(i));
connect(pAction, SIGNAL(triggered()), this, SLOT(OnMenu()));
m_pMenu->addAction(pAction);
m_Columns[pAction] = i;
}
if (m_ColumnReset)
{
m_pMenu->addSeparator();
QAction* pAction = m_pMenu->addAction(tr("Reset columns"));
if(m_ColumnReset == 1)
connect(pAction, SIGNAL(triggered()), this, SLOT(OnResetColumns()));
else
connect(pAction, SIGNAL(triggered()), this, SIGNAL(ResetColumns()));
}
}
for(QMap<QAction*, int>::iterator I = m_Columns.begin(); I != m_Columns.end(); I++)
I.key()->setChecked(!isColumnHidden(I.value()));
m_pMenu->popup(QCursor::pos());
}
void OnMenu()
{
QAction* pAction = (QAction*)sender();
int Column = m_Columns.value(pAction, -1);
SetColumnHidden(Column, !pAction->isChecked());
}
protected:
QMenu* m_pMenu;
QMap<QAction*, int> m_Columns;
QSet<int> m_FixedColumns;
int m_ColumnReset;
};
class MISCHELPERS_EXPORT QStyledItemDelegateMaxH : public QStyledItemDelegate
{
Q_OBJECT
public:
QStyledItemDelegateMaxH(int MaxHeight, QObject *parent = 0)
: QStyledItemDelegate(parent) {m_MaxHeight = MaxHeight;}
QSize sizeHint(const QStyleOptionViewItem &option, const QModelIndex &index) const
{
QSize size = QStyledItemDelegate::sizeHint(option, index);
size.setHeight(m_MaxHeight);
return size;
}
int m_MaxHeight;
};
class MISCHELPERS_EXPORT CStyledGridItemDelegate : public QStyledItemDelegateMaxH
{
public:
explicit CStyledGridItemDelegate(int MaxHeight, QObject * parent = 0) : CStyledGridItemDelegate(MaxHeight, false, parent) { }
explicit CStyledGridItemDelegate(int MaxHeight, QColor Color, QObject * parent = 0) : CStyledGridItemDelegate(MaxHeight, Color, false, parent) { }
explicit CStyledGridItemDelegate(int MaxHeight, bool Tree, QObject * parent = 0) : CStyledGridItemDelegate(MaxHeight, QColor(Qt::darkGray), false, parent) { }
explicit CStyledGridItemDelegate(int MaxHeight, QColor Color, bool Tree, QObject * parent = 0) : QStyledItemDelegateMaxH(MaxHeight, parent) {
m_Color = Color;
m_Tree = Tree;
m_Grid = true;
}
void paint(QPainter * painter, const QStyleOptionViewItem & option, const QModelIndex & index ) const
{
QStyledItemDelegate::paint(painter, option, index);
if (m_Grid)
{
painter->save();
painter->setPen(m_Color);
//painter->drawRect(option.rect);
//painter->drawLine(option.rect.left(), option.rect.top(), option.rect.right(), option.rect.top());
painter->drawLine(option.rect.right(), option.rect.top(), option.rect.right(), option.rect.bottom());
painter->drawLine(option.rect.left() + (m_Tree && index.column() == 0 ? 24 : 0), option.rect.bottom(), option.rect.right(), option.rect.bottom());
painter->restore();
}
}
bool m_Grid;
bool m_Tree;
QColor m_Color;
};

View File

@ -0,0 +1,150 @@
#pragma once
#include "../mischelpers_global.h"
class MISCHELPERS_EXPORT QTreeWidgetEx: public QTreeWidget
{
Q_OBJECT
public:
QTreeWidgetEx(QWidget *parent = 0) : QTreeWidget(parent)
{
setUniformRowHeights(true);
m_AutoFitMax = 0;
m_ColumnReset = 1;
header()->setContextMenuPolicy(Qt::CustomContextMenu);
connect(header(), SIGNAL(customContextMenuRequested( const QPoint& )), this, SLOT(OnMenuRequested(const QPoint &)));
m_pMenu = new QMenu(this);
// Important: if something is shown/hidden we need a new size
connect(this->model(), SIGNAL(rowsInserted(const QModelIndex &, int, int)), this, SLOT(OnExpandCollapsed()));
connect(this->model(), SIGNAL(rowsRemoved(const QModelIndex &, int, int)), this, SLOT(OnExpandCollapsed()));
//connect(this->header(), SIGNAL(geometriesChanged()), this, SLOT(OnExpandCollapsed())); // fixme
connect(this, SIGNAL(expanded(const QModelIndex &)), this, SLOT(OnExpandCollapsed()));
connect(this, SIGNAL(collapsed(const QModelIndex &)), this, SLOT(OnExpandCollapsed()));
}
static void AddSubItem(QTreeWidgetItem* pRoot, const QString& Key, const QString& Value)
{
QTreeWidgetItem* pItem = new QTreeWidgetItem(QStringList(Key));
pItem->setText(1, Value);
pRoot->addChild(pItem);
}
// Use this function to make the widget autosize to show all items up to this value
void setAutoFitMax(int AutoFitMax)
{
m_AutoFitMax = AutoFitMax;
}
void setColumnReset(int iMode)
{
m_ColumnReset = iMode;
}
QSize sizeHint() const {return m_AutoFitMax ? MySize() : QTreeWidget::sizeHint(); };
QSize minimumSizeHint() const { return m_AutoFitMax ? MySize() : QTreeWidget::sizeHint(); };
signals:
void ResetColumns();
public slots:
void OnResetColumns()
{
for (int i = 0; i < columnCount(); i++)
setColumnHidden(i, false);
}
private slots:
void OnMenuRequested(const QPoint &point)
{
if(m_Columns.isEmpty())
{
QTreeWidgetItem* pHeader = headerItem();
for(int i=0; i < columnCount(); i++)
{
QAction* pAction = new QAction(pHeader->text(i), m_pMenu);
pAction->setCheckable(true);
connect(pAction, SIGNAL(triggered()), this, SLOT(OnMenu()));
m_pMenu->addAction(pAction);
m_Columns[pAction] = i;
}
if (m_ColumnReset)
{
m_pMenu->addSeparator();
QAction* pAction = m_pMenu->addAction(tr("Reset columns"));
if(m_ColumnReset == 1)
connect(pAction, SIGNAL(triggered()), this, SLOT(OnResetColumns()));
else
connect(pAction, SIGNAL(triggered()), this, SIGNAL(ResetColumns()));
}
}
for(QMap<QAction*, int>::iterator I = m_Columns.begin(); I != m_Columns.end(); I++)
I.key()->setChecked(!isColumnHidden(I.value()));
m_pMenu->popup(QCursor::pos());
}
void OnMenu()
{
QAction* pAction = (QAction*)sender();
int Column = m_Columns.value(pAction, -1);
setColumnHidden(Column, !pAction->isChecked());
QTimer::singleShot(10, this, SLOT(OnExpandCollapsed()));
}
void OnExpandCollapsed()
{
if (m_AutoFitMax)
updateGeometry();
}
protected:
QSize MySize() const
{ //QSize tst(sizeHintForColumn(0) + 2 * frameWidth(), sizeHintForRow(0) + 2 * frameWidth());
int neededHight= 2 * frameWidth()+ this->header()->height();
QAbstractItemModel* m = this->model();
QModelIndex root = this->rootIndex();
//if(this->rootIsDecorated())
neededHight += recursiveHeightHint(root,m);
if (this->horizontalScrollBar()->isVisible())
neededHight += this->horizontalScrollBar()->height();
if (neededHight > m_AutoFitMax)
neededHight = m_AutoFitMax;
QSize temp = QTreeView::sizeHint();
temp.setHeight(neededHight);
return QSize(1,neededHight);
}
// we need the size of all visible items -> isExpanded
// the root item is usually shown as a non-Valid index -> !i.isValid()
int recursiveHeightHint(QModelIndex i,QAbstractItemModel* m) const
{
int temp=sizeHintForIndex(i).height() + 1;
if(this->isExpanded(i) || !i.isValid())
{
if(m->hasChildren(i))
{
int numRows = m->rowCount(i);
for(int count =0;count<numRows;count++)
temp+=recursiveHeightHint(m->index(count,0,i),m);
}
}
return temp;
}
QMenu* m_pMenu;
QMap<QAction*, int> m_Columns;
int m_AutoFitMax;
int m_ColumnReset;
};

View File

@ -0,0 +1,289 @@
#include "stdafx.h"
#include "Xml.h"
QString CXml::Serialize(const QVariant &Variant, bool bLazy)
{
QString String;
QXmlStreamWriter xml(&String);
Serialize(Variant, xml, bLazy);
return String;
}
QVariant CXml::Parse(const QString& String, bool bLazy)
{
QXmlStreamReader xml(String);
return Parse(xml, bLazy);
}
void CXml::Serialize(const QVariant& Variant, QFile* pFile)
{
QXmlStreamWriter xml(pFile);
Serialize(Variant, xml);
}
QVariant CXml::Parse(QFile* pFile)
{
QXmlStreamReader xml(pFile);
return Parse(xml);
}
void CXml::Write(const QVariant& Variant, const QString& FileName)
{
QFile File(FileName + ".tmp");
File.open(QFile::WriteOnly);
Serialize(Variant, &File);
QFile::rename(FileName, FileName + ".bak");
File.rename(FileName);
File.remove(FileName + ".bak");
}
QVariant CXml::Read(const QString& FileName)
{
QFile File(FileName);
File.open(QFile::ReadOnly);
return Parse(&File);
}
void CXml::Serialize(const QVariant& Variant, QXmlStreamWriter &xml, bool bLazy)
{
#ifdef _DEBUG
xml.setAutoFormatting(true);
#endif
xml.writeStartDocument();
Serialize("Variant", Variant, xml, bLazy);
xml.writeEndDocument();
}
QVariant CXml::Parse(QXmlStreamReader &xml, bool bLazy)
{
QVariant Variant;
QString Temp;
Parse(Temp, Variant, xml, bLazy);
return Variant;
}
void CXml::Serialize(const QString& Name, const QVariant& Variant, QXmlStreamWriter &xml, bool bLazy)
{
xml.writeStartElement(Name);
xml.writeAttribute("Type", GetTypeStr(Variant.type()));
switch(Variant.type())
{
case QVariant::Map:
{
QVariantMap Map = Variant.toMap();
for(QVariantMap::iterator I = Map.begin(); I != Map.end(); ++I)
Serialize(I.key(), I.value(), xml, bLazy);
break;
}
case QVariant::Hash:
{
QVariantHash Hash = Variant.toHash();
for(QVariantHash::iterator I = Hash.begin(); I != Hash.end(); ++I)
Serialize(I.key(), I.value(), xml, bLazy);
break;
}
case QVariant::List:
{
QVariantList List = Variant.toList();
for(QVariantList::iterator I = List.begin(); I != List.end(); ++I)
Serialize("Variant", *I, xml, bLazy);
break;
}
case QVariant::StringList:
{
QStringList List = Variant.toStringList();
for(QStringList::iterator I = List.begin(); I != List.end(); ++I)
Serialize("Variant", *I, xml, bLazy);
break;
}
case QVariant::ByteArray:
if(!bLazy)
{
xml.writeCharacters (Variant.toByteArray().toBase64());
break;
}
default:
ASSERT(Variant.canConvert(QVariant::String));
xml.writeCharacters(Variant.toString().toUtf8().toPercentEncoding(" :;/|,'+()"));
//xml.writeCharacters (Variant.toString().replace("\\","\\\\").replace("\r","\\r").replace("\n","\\n"));
break;
case QVariant::Invalid:
break;
}
xml.writeEndElement();
}
bool CXml::Parse(QString &Name, QVariant &Variant, QXmlStreamReader &xml, bool bLazy)
{
bool bOpen = false;
QVariant::Type eType = QVariant::Invalid;
QString Text;
while (!xml.atEnd())
{
xml.readNext();
if (xml.error())
break;
if (xml.isEndDocument())
continue;
if (xml.isStartElement())
{
bOpen = true;
Name = xml.name().toString();
eType = GetType(xml.attributes().value("Type").toString());
QString Temp;
QVariant Item;
switch(eType)
{
case QVariant::Map:
{
QVariantMap Map;
while(Parse(Temp, Item, xml, bLazy))
Map.insert(Temp, Item);
Variant = Map;
return true;
}
case QVariant::Hash:
{
QVariantHash Hash;
while(Parse(Temp, Item, xml, bLazy))
Hash.insert(Temp, Item);
Variant = Hash;
return true;
}
case QVariant::List:
{
QVariantList List;
while(Parse(Temp, Item, xml, bLazy))
List.append(Item);
Variant = List;
return true;
}
case QVariant::StringList:
{
QStringList List;
while(Parse(Temp, Item, xml, bLazy))
List.append(Item.toString());
Variant = List;
return true;
}
}
}
else if (xml.isCharacters())
{
if(bOpen)
Text.append(xml.text().toString());
}
else if (xml.isEndElement())
{
if(bOpen)
{
if(eType == QVariant::ByteArray && !bLazy)
Variant.setValue(QByteArray::fromBase64(Text.toLatin1()));
else
{
/*bool bEsc = false;
for(int i = 0; i < Text.size(); i++)
{
if(bEsc) // ESC sequence handling
{
switch(Text.at(i).unicode())
{
case L'\\': Text.replace(--i,2,"\\"); break;
case L'r': Text.replace(--i,2,"\r"); break;
case L'n': Text.replace(--i,2,"\n"); break;
default: Text.replace(--i,2,"?"); break;
}
bEsc = false;
}
else if(Text.at(i) == L'\\')
bEsc = true;
}*/
Variant = QString::fromUtf8(QByteArray::fromPercentEncoding(Text.toLatin1()));
if(eType) // type is optional
{
ASSERT(Variant.canConvert(eType));
Variant.convert(eType);
}
}
return true;
}
return false;
}
}
//ASSERT(0); // incomplete XML
return false;
}
/* SQVariants provides a lookup list of all known QVariant types for to/from string conversion
*
* Note: All commented out types dont have native to string converion
* If there is a need to use them a manual conversion must be implemented in CXml
*/
struct SQVariants{
SQVariants()
{
Map.insert("Invalid" , QVariant::Invalid);
Map.insert("Bool" , QVariant::Bool);
Map.insert("Int" , QVariant::Int);
Map.insert("UInt" , QVariant::UInt);
Map.insert("LongLong" , QVariant::LongLong);
Map.insert("ULongLong" , QVariant::ULongLong);
Map.insert("Double" , QVariant::Double);
Map.insert("Char" , QVariant::Char);
Map.insert("Map" , QVariant::Map); // conainter type
Map.insert("List" , QVariant::List); // conainter type
Map.insert("String" , QVariant::String);
Map.insert("StringList" , QVariant::StringList); // conainter type
Map.insert("ByteArray" , QVariant::ByteArray);
//Map.insert("BitArray" , QVariant::BitArray);
Map.insert("Date" , QVariant::Date);
Map.insert("Time" , QVariant::Time);
Map.insert("DateTime" , QVariant::DateTime);
Map.insert("Url" , QVariant::Url);
/*Map.insert("Locale" , 18);
Map.insert("Rect" , 19);
Map.insert("RectF" , 20);
Map.insert("Size" , 21);
Map.insert("SizeF" , 22);
Map.insert("Line" , 23);
Map.insert("LineF" , 24);
Map.insert("Point" , 25);
Map.insert("PointF" , 26);
Map.insert("RegExp" , 27);*/
Map.insert("Hash" , QVariant::Hash); // conainter type
/*Map.insert("Font" , 64);
Map.insert("Pixmap" , 65);
Map.insert("Brush" , 66);
Map.insert("Color" , 67);
Map.insert("Palette" , 68);
Map.insert("Icon" , 69);
Map.insert("Image" , 70);
Map.insert("Polygon" , 71);
Map.insert("Region" , 72);
Map.insert("Bitmap" , 73);
Map.insert("Cursor" , 74);
Map.insert("SizePolicy" , 75);
Map.insert("KeySequence", 76);
Map.insert("Pen" , 77);
Map.insert("TextLength" , 78);
Map.insert("TextFormat" , 79);
Map.insert("Matrix" , 80);
Map.insert("Transform" , 81);
Map.insert("Matrix4x4" , 82);
Map.insert("Vector2D" , 83);
Map.insert("Vector3D" , 84);
Map.insert("Vector4D" , 85);
Map.insert("Quaternion" , 86);*/
}
QMap<QString,int> Map;
} SQVariants;
QString CXml::GetTypeStr(int Type) {return SQVariants.Map.key(Type, "Invalid");}
QVariant::Type CXml::GetType(QString Type) {return (QVariant::Type)SQVariants.Map.value(Type, 0);}

View File

@ -0,0 +1,25 @@
#pragma once
#include "../mischelpers_global.h"
class MISCHELPERS_EXPORT CXml {
public:
static QString Serialize(const QVariant& Variant, bool bLazy = false);
static QVariant Parse(const QString& String, bool bLazy = false);
static void Serialize(const QVariant& Variant, QFile* pFile);
static QVariant Parse(QFile* pFile);
static void Write(const QVariant& Variant, const QString& FileName);
static QVariant Read(const QString& FileName);
protected:
static void Serialize(const QVariant& Variant, QXmlStreamWriter &xml, bool bLazy = false);
static QVariant Parse(QXmlStreamReader &xml, bool bLazy = false);
static void Serialize(const QString& Name, const QVariant& Variant, QXmlStreamWriter &xml, bool bLazy = false);
static bool Parse(QString &Name, QVariant &Variant, QXmlStreamReader &xml, bool bLazy = false);
static QString GetTypeStr(int Type);
static QVariant::Type GetType(QString Type);
};

View File

@ -0,0 +1,6 @@
#include "stdafx.h"
#include "MiscHelpers.h"
MiscHelpers::MiscHelpers()
{
}

View File

@ -0,0 +1,35 @@
#pragma once
#include "mischelpers_global.h"
#include ".\Common\CheckableMessageBox.h"
#include ".\Common\ComboInputDialog.h"
#include ".\Common\Common.h"
#include ".\Common\DebugHelpers.h"
#include ".\Common\ExitDialog.h"
#include ".\Common\Finder.h"
#include ".\Common\FlexError.h"
#include ".\Common\FlowLayout.h"
#include ".\Common\HistoryGraph.h"
#include ".\Common\ItemChooser.h"
#include ".\Common\KeyValueInputDialog.h"
#include ".\Common\ListItemModel.h"
#include ".\Common\MultiLineInputDialog.h"
#include ".\Common\PanelView.h"
#include ".\Common\ProgressDialog.h"
#include ".\Common\Settings.h"
#include ".\Common\SettingsWidgets.h"
#include ".\Common\SmartGridWidget.h"
#include ".\Common\SortFilterProxyModel.h"
#include ".\Common\SplitTreeView.h"
#include ".\Common\TabPanel.h"
#include ".\Common\TreeItemModel.h"
#include ".\Common\TreeViewEx.h"
#include ".\Common\TreeWidgetEx.h"
#include ".\Common\Xml.h"
class MISCHELPERS_EXPORT MiscHelpers
{
public:
MiscHelpers();
};

View File

@ -0,0 +1,166 @@
<?xml version="1.0" encoding="utf-8"?>
<Project DefaultTargets="Build" ToolsVersion="15.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<ItemGroup Label="ProjectConfigurations">
<ProjectConfiguration Include="Debug|x64">
<Configuration>Debug</Configuration>
<Platform>x64</Platform>
</ProjectConfiguration>
<ProjectConfiguration Include="Release|x64">
<Configuration>Release</Configuration>
<Platform>x64</Platform>
</ProjectConfiguration>
</ItemGroup>
<PropertyGroup Label="Globals">
<ProjectGuid>{7AB8215A-59A4-4B8B-8090-16C87A860429}</ProjectGuid>
<Keyword>QtVS_v302</Keyword>
<WindowsTargetPlatformVersion>10.0.17763.0</WindowsTargetPlatformVersion>
<QtMsBuild Condition="'$(QtMsBuild)'=='' OR !Exists('$(QtMsBuild)\qt.targets')">$(MSBuildProjectDirectory)\QtMsBuild</QtMsBuild>
</PropertyGroup>
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" />
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'" Label="Configuration">
<ConfigurationType>DynamicLibrary</ConfigurationType>
<PlatformToolset>v140</PlatformToolset>
<SpectreMitigation>false</SpectreMitigation>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'" Label="Configuration">
<ConfigurationType>DynamicLibrary</ConfigurationType>
<PlatformToolset>v141</PlatformToolset>
<SpectreMitigation>false</SpectreMitigation>
</PropertyGroup>
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" />
<Target Name="QtMsBuildNotFound" BeforeTargets="CustomBuild;ClCompile" Condition="!Exists('$(QtMsBuild)\qt.targets') or !Exists('$(QtMsBuild)\qt.props')">
<Message Importance="High" Text="QtMsBuild: could not locate qt.targets, qt.props; project may not build correctly." />
</Target>
<ImportGroup Label="ExtensionSettings" />
<ImportGroup Label="Shared" />
<ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
</ImportGroup>
<ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
</ImportGroup>
<PropertyGroup Label="UserMacros" />
<ImportGroup Condition="Exists('$(QtMsBuild)\qt_defaults.props')">
<Import Project="$(QtMsBuild)\qt_defaults.props" />
</ImportGroup>
<PropertyGroup Label="QtSettings" Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
<QtInstall>msvc2015_64</QtInstall>
<QtModules>core;network;widgets;winextras</QtModules>
</PropertyGroup>
<PropertyGroup Label="QtSettings" Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
<QtInstall>msvc2017_64_dbg</QtInstall>
<QtModules>core;network;widgets;winextras</QtModules>
</PropertyGroup>
<ImportGroup Condition="Exists('$(QtMsBuild)\qt.props')">
<Import Project="$(QtMsBuild)\qt.props" />
</ImportGroup>
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
<QtMoc>
<PrependInclude>stdafx.h</PrependInclude>
</QtMoc>
<ClCompile>
<MultiProcessorCompilation>true</MultiProcessorCompilation>
<Optimization>Disabled</Optimization>
<DebugInformationFormat>ProgramDatabase</DebugInformationFormat>
<RuntimeLibrary>MultiThreadedDebugDLL</RuntimeLibrary>
<TreatWChar_tAsBuiltInType>true</TreatWChar_tAsBuiltInType>
<PrecompiledHeader>Use</PrecompiledHeader>
<PrecompiledHeaderFile>stdafx.h</PrecompiledHeaderFile>
<PrecompiledHeaderOutputFile>$(IntDir)$(TargetName).pch</PrecompiledHeaderOutputFile>
<PreprocessorDefinitions>MISCHELPERS_LIB;%(PreprocessorDefinitions)</PreprocessorDefinitions>
</ClCompile>
<Link>
<SubSystem>Windows</SubSystem>
<OutputFile>$(OutDir)\$(ProjectName).dll</OutputFile>
<GenerateDebugInformation>true</GenerateDebugInformation>
</Link>
</ItemDefinitionGroup>
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
<QtMoc>
<PrependInclude>stdafx.h</PrependInclude>
</QtMoc>
<ClCompile>
<MultiProcessorCompilation>true</MultiProcessorCompilation>
<DebugInformationFormat />
<RuntimeLibrary>MultiThreadedDLL</RuntimeLibrary>
<TreatWChar_tAsBuiltInType>true</TreatWChar_tAsBuiltInType>
<PrecompiledHeader>Use</PrecompiledHeader>
<PrecompiledHeaderFile>stdafx.h</PrecompiledHeaderFile>
<PrecompiledHeaderOutputFile>$(IntDir)$(TargetName).pch</PrecompiledHeaderOutputFile>
<PreprocessorDefinitions>MISCHELPERS_LIB;%(PreprocessorDefinitions)</PreprocessorDefinitions>
</ClCompile>
<Link>
<SubSystem>Windows</SubSystem>
<OutputFile>$(OutDir)\$(ProjectName).dll</OutputFile>
<GenerateDebugInformation>false</GenerateDebugInformation>
</Link>
</ItemDefinitionGroup>
<ItemGroup>
<ClCompile Include="Common\CheckableMessageBox.cpp" />
<ClCompile Include="Common\ComboInputDialog.cpp" />
<ClCompile Include="Common\Common.cpp" />
<ClCompile Include="Common\DebugHelpers.cpp" />
<ClCompile Include="Common\Finder.cpp" />
<ClCompile Include="Common\FlowLayout.cpp" />
<ClCompile Include="Common\IconExtreactor.cpp" />
<ClCompile Include="Common\ItemChooser.cpp" />
<ClCompile Include="Common\KeyValueInputDialog.cpp" />
<ClCompile Include="Common\ListItemModel.cpp" />
<ClCompile Include="Common\MultiLineInputDialog.cpp" />
<ClCompile Include="Common\PanelView.cpp" />
<ClCompile Include="Common\Settings.cpp" />
<ClCompile Include="Common\SettingsWidgets.cpp" />
<ClCompile Include="Common\SmartGridWidget.cpp" />
<ClCompile Include="Common\SplitTreeView.cpp" />
<ClCompile Include="Common\TabPanel.cpp" />
<ClCompile Include="Common\TreeItemModel.cpp" />
<ClCompile Include="Common\Xml.cpp" />
<ClCompile Include="MiscHelpers.cpp" />
<ClCompile Include="stdafx.cpp">
<PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">Create</PrecompiledHeader>
<PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Release|x64'">Create</PrecompiledHeader>
</ClCompile>
</ItemGroup>
<ItemGroup>
<QtMoc Include="Common\CheckableMessageBox.h" />
<QtMoc Include="Common\ComboInputDialog.h" />
<ClInclude Include="Common\Common.h" />
<ClInclude Include="Common\DebugHelpers.h" />
<ClInclude Include="Common\ExitDialog.h" />
<QtMoc Include="Common\Finder.h" />
<ClInclude Include="Common\FlexError.h" />
<ClInclude Include="Common\FlowLayout.h" />
<ClInclude Include="Common\HistoryGraph.h" />
<QtMoc Include="Common\ItemChooser.h" />
<QtMoc Include="Common\KeyValueInputDialog.h" />
<QtMoc Include="Common\ListItemModel.h" />
<QtMoc Include="Common\MultiLineInputDialog.h" />
<QtMoc Include="Common\PanelView.h" />
<QtMoc Include="Common\ProgressDialog.h" />
<QtMoc Include="Common\Settings.h" />
<QtMoc Include="Common\SettingsWidgets.h" />
<QtMoc Include="Common\SmartGridWidget.h" />
<QtMoc Include="Common\SortFilterProxyModel.h" />
<QtMoc Include="Common\SplitTreeView.h" />
<QtMoc Include="Common\TabPanel.h" />
<QtMoc Include="Common\TreeItemModel.h" />
<QtMoc Include="Common\TreeViewEx.h" />
<QtMoc Include="Common\TreeWidgetEx.h" />
<ClInclude Include="Common\IconExtreactor.h" />
<ClInclude Include="Common\Xml.h" />
<ClInclude Include="MiscHelpers.h" />
<ClInclude Include="mischelpers_global.h" />
<ClInclude Include="stdafx.h" />
</ItemGroup>
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
<ImportGroup Condition="Exists('$(QtMsBuild)\qt.targets')">
<Import Project="$(QtMsBuild)\qt.targets" />
</ImportGroup>
<ImportGroup Label="ExtensionTargets">
</ImportGroup>
<ProjectExtensions>
<VisualStudio>
<UserProperties MocDir=".\GeneratedFiles\$(ConfigurationName)" UicDir=".\GeneratedFiles" RccDir=".\GeneratedFiles" lupdateOptions="" lupdateOnBuild="0" lreleaseOptions="" MocOptions="" />
</VisualStudio>
</ProjectExtensions>
</Project>

View File

@ -0,0 +1,184 @@
<?xml version="1.0" encoding="utf-8"?>
<Project ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<ItemGroup>
<Filter Include="Source Files">
<UniqueIdentifier>{4FC737F1-C7A5-4376-A066-2A32D752A2FF}</UniqueIdentifier>
<Extensions>cpp;c;cc;cxx;def;odl;idl;hpj;bat;asm;asmx</Extensions>
</Filter>
<Filter Include="Header Files">
<UniqueIdentifier>{93995380-89BD-4b04-88EB-625FBE52EBFB}</UniqueIdentifier>
<Extensions>h;hh;hpp;hxx;hm;inl;inc;xsd</Extensions>
</Filter>
<Filter Include="Resource Files">
<UniqueIdentifier>{D9D6E242-F8AF-46E4-B9FD-80ECBC20BA3E}</UniqueIdentifier>
<Extensions>qrc;*</Extensions>
<ParseFiles>false</ParseFiles>
</Filter>
<Filter Include="Resource Files">
<UniqueIdentifier>{D9D6E242-F8AF-46E4-B9FD-80ECBC20BA3E}</UniqueIdentifier>
<Extensions>qrc;*</Extensions>
<ParseFiles>false</ParseFiles>
</Filter>
<Filter Include="Common">
<UniqueIdentifier>{964acff8-ecee-4dfc-939d-e2406a533100}</UniqueIdentifier>
</Filter>
</ItemGroup>
<ItemGroup>
<ClCompile Include="MiscHelpers.cpp">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="stdafx.cpp">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="Common\CheckableMessageBox.cpp">
<Filter>Common</Filter>
</ClCompile>
<ClCompile Include="Common\ComboInputDialog.cpp">
<Filter>Common</Filter>
</ClCompile>
<ClCompile Include="Common\Common.cpp">
<Filter>Common</Filter>
</ClCompile>
<ClCompile Include="Common\DebugHelpers.cpp">
<Filter>Common</Filter>
</ClCompile>
<ClCompile Include="Common\Finder.cpp">
<Filter>Common</Filter>
</ClCompile>
<ClCompile Include="Common\FlowLayout.cpp">
<Filter>Common</Filter>
</ClCompile>
<ClCompile Include="Common\ItemChooser.cpp">
<Filter>Common</Filter>
</ClCompile>
<ClCompile Include="Common\KeyValueInputDialog.cpp">
<Filter>Common</Filter>
</ClCompile>
<ClCompile Include="Common\ListItemModel.cpp">
<Filter>Common</Filter>
</ClCompile>
<ClCompile Include="Common\MultiLineInputDialog.cpp">
<Filter>Common</Filter>
</ClCompile>
<ClCompile Include="Common\PanelView.cpp">
<Filter>Common</Filter>
</ClCompile>
<ClCompile Include="Common\Settings.cpp">
<Filter>Common</Filter>
</ClCompile>
<ClCompile Include="Common\SettingsWidgets.cpp">
<Filter>Common</Filter>
</ClCompile>
<ClCompile Include="Common\SmartGridWidget.cpp">
<Filter>Common</Filter>
</ClCompile>
<ClCompile Include="Common\SplitTreeView.cpp">
<Filter>Common</Filter>
</ClCompile>
<ClCompile Include="Common\TabPanel.cpp">
<Filter>Common</Filter>
</ClCompile>
<ClCompile Include="Common\TreeItemModel.cpp">
<Filter>Common</Filter>
</ClCompile>
<ClCompile Include="Common\Xml.cpp">
<Filter>Common</Filter>
</ClCompile>
<ClCompile Include="Common\IconExtreactor.cpp">
<Filter>Common</Filter>
</ClCompile>
</ItemGroup>
<ItemGroup>
<ClInclude Include="MiscHelpers.h">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="stdafx.h">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="Common\Common.h">
<Filter>Common</Filter>
</ClInclude>
<ClInclude Include="Common\DebugHelpers.h">
<Filter>Common</Filter>
</ClInclude>
<ClInclude Include="Common\ExitDialog.h">
<Filter>Common</Filter>
</ClInclude>
<ClInclude Include="Common\FlexError.h">
<Filter>Common</Filter>
</ClInclude>
<ClInclude Include="Common\FlowLayout.h">
<Filter>Common</Filter>
</ClInclude>
<ClInclude Include="Common\HistoryGraph.h">
<Filter>Common</Filter>
</ClInclude>
<ClInclude Include="Common\Xml.h">
<Filter>Common</Filter>
</ClInclude>
<ClInclude Include="Common\IconExtreactor.h">
<Filter>Common</Filter>
</ClInclude>
</ItemGroup>
<ItemGroup>
<ClInclude Include="mischelpers_global.h">
<Filter>Header Files</Filter>
</ClInclude>
</ItemGroup>
<ItemGroup>
<QtMoc Include="Common\CheckableMessageBox.h">
<Filter>Common</Filter>
</QtMoc>
<QtMoc Include="Common\ComboInputDialog.h">
<Filter>Common</Filter>
</QtMoc>
<QtMoc Include="Common\Finder.h">
<Filter>Common</Filter>
</QtMoc>
<QtMoc Include="Common\ItemChooser.h">
<Filter>Common</Filter>
</QtMoc>
<QtMoc Include="Common\KeyValueInputDialog.h">
<Filter>Common</Filter>
</QtMoc>
<QtMoc Include="Common\ListItemModel.h">
<Filter>Common</Filter>
</QtMoc>
<QtMoc Include="Common\MultiLineInputDialog.h">
<Filter>Common</Filter>
</QtMoc>
<QtMoc Include="Common\PanelView.h">
<Filter>Common</Filter>
</QtMoc>
<QtMoc Include="Common\ProgressDialog.h">
<Filter>Common</Filter>
</QtMoc>
<QtMoc Include="Common\Settings.h">
<Filter>Common</Filter>
</QtMoc>
<QtMoc Include="Common\SettingsWidgets.h">
<Filter>Common</Filter>
</QtMoc>
<QtMoc Include="Common\SmartGridWidget.h">
<Filter>Common</Filter>
</QtMoc>
<QtMoc Include="Common\SortFilterProxyModel.h">
<Filter>Common</Filter>
</QtMoc>
<QtMoc Include="Common\SplitTreeView.h">
<Filter>Common</Filter>
</QtMoc>
<QtMoc Include="Common\TabPanel.h">
<Filter>Common</Filter>
</QtMoc>
<QtMoc Include="Common\TreeItemModel.h">
<Filter>Common</Filter>
</QtMoc>
<QtMoc Include="Common\TreeViewEx.h">
<Filter>Common</Filter>
</QtMoc>
<QtMoc Include="Common\TreeWidgetEx.h">
<Filter>Common</Filter>
</QtMoc>
</ItemGroup>
</Project>

View File

@ -0,0 +1,4 @@
<?xml version="1.0" encoding="utf-8"?>
<Project ToolsVersion="15.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<PropertyGroup />
</Project>

View File

@ -0,0 +1,13 @@
#pragma once
#include <QtCore/qglobal.h>
#ifndef BUILD_STATIC
# if defined(MISCHELPERS_LIB)
# define MISCHELPERS_EXPORT Q_DECL_EXPORT
# else
# define MISCHELPERS_EXPORT Q_DECL_IMPORT
# endif
#else
# define MISCHELPERS_EXPORT
#endif

View File

@ -0,0 +1 @@
#include "stdafx.h"

View File

@ -0,0 +1,135 @@
#pragma once
#define _CRT_SECURE_NO_WARNINGS
// std includes
#include <string>
#include <sstream>
#include <deque>
#include <list>
#include <vector>
#include <map>
#include <set>
#include <memory>
using namespace std;
// Qt includes
#include <QObject>
#include <QList>
#include <QVector>
#include <QMap>
#include <QString>
#include <QStringList>
#include <QUrl>
#include <QFile>
#include <qglobal.h>
#include <QTime>
#include <QTimer>
#include <QTimerEvent>
#include <QThread>
#include <QProcess>
#include <QNetworkAccessManager>
#include <QNetworkCookieJar>
#include <QNetworkRequest>
#include <QNetworkReply>
#include <QNetworkProxy>
#include <QNetworkDiskCache>
#include <QTextStream>
#include <QFileInfo>
#include <QXmlStreamWriter>
#include <QLocalServer>
#include <QLocalSocket>
#include <QTcpServer>
#include <QTcpSocket>
#include <QUdpSocket>
#include <QBuffer>
#include <QDir>
#include <QTemporaryFile>
#include <QMutex>
#include <QMutexLocker>
#include <QReadWriteLock>
#include <QWaitCondition>
#include <QBitArray>
#include <QPointer>
#include <QSharedPointer>
#include <QFutureWatcher>
#include <QHostInfo>
#include <QApplication>
#include <QClipboard>
#include <QMainWindow>
#include <QWidget>
#include <QHBoxLayout>
#include <QMenu>
#include <QAction>
#include <QSplitter>
#include <QTabWidget>
#include <QTextEdit>
#include <QLabel>
#include <QMenuBar>
#include <QStatusBar>
#include <QCloseEvent>
#include <QFileDialog>
#include <QMessageBox>
#include <QHeaderView>
#include <QToolBar>
#include <QScrollBar>
#include <QStyleFactory>
#include <QSortFilterProxyModel>
#include <QStackedLayout>
#include <QTreeWidget>
#include <QFormLayout>
#include <QLineEdit>
#include <QTextEdit>
#include <QWidgetAction>
#include <QCheckBox>
#include <QScrollArea>
#include <QDialogButtonBox>
#include <QStandardItemModel>
#include <QPainter>
#include <QGroupBox>
#include <QSpinBox>
#include <QComboBox>
#include <QPlainTextEdit>
#include <QPushButton>
#include <QSystemTrayIcon>
#include <QDesktopServices>
#include <QFileDialog>
#include <QProgressBar>
#include <QInputDialog>
#include <QToolTip>
#include <QColorDialog>
#include <QToolButton>
#include <QScreen>
#include <QIdentityProxyModel>
#include <QRandomGenerator>
#include <QElapsedTimer>
// other includes
#define _T(x) L ## x
#define STR2(X) #X
#define STR(X) STR2(X)
#define ARRSIZE(x) (sizeof(x)/sizeof(x[0]))
#ifndef Max
#define Max(a,b) (((a) > (b)) ? (a) : (b))
#endif
#ifndef Min
#define Min(a,b) (((a) < (b)) ? (a) : (b))
#endif
#ifdef _DEBUG
#define SAFE_MODE
#endif
#include "Common/DebugHelpers.h"
//#define USE_QEXTWIDGETS

View File

@ -0,0 +1,165 @@
GNU LESSER GENERAL PUBLIC LICENSE
Version 3, 29 June 2007
Copyright (C) 2007 Free Software Foundation, Inc. <https://fsf.org/>
Everyone is permitted to copy and distribute verbatim copies
of this license document, but changing it is not allowed.
This version of the GNU Lesser General Public License incorporates
the terms and conditions of version 3 of the GNU General Public
License, supplemented by the additional permissions listed below.
0. Additional Definitions.
As used herein, "this License" refers to version 3 of the GNU Lesser
General Public License, and the "GNU GPL" refers to version 3 of the GNU
General Public License.
"The Library" refers to a covered work governed by this License,
other than an Application or a Combined Work as defined below.
An "Application" is any work that makes use of an interface provided
by the Library, but which is not otherwise based on the Library.
Defining a subclass of a class defined by the Library is deemed a mode
of using an interface provided by the Library.
A "Combined Work" is a work produced by combining or linking an
Application with the Library. The particular version of the Library
with which the Combined Work was made is also called the "Linked
Version".
The "Minimal Corresponding Source" for a Combined Work means the
Corresponding Source for the Combined Work, excluding any source code
for portions of the Combined Work that, considered in isolation, are
based on the Application, and not on the Linked Version.
The "Corresponding Application Code" for a Combined Work means the
object code and/or source code for the Application, including any data
and utility programs needed for reproducing the Combined Work from the
Application, but excluding the System Libraries of the Combined Work.
1. Exception to Section 3 of the GNU GPL.
You may convey a covered work under sections 3 and 4 of this License
without being bound by section 3 of the GNU GPL.
2. Conveying Modified Versions.
If you modify a copy of the Library, and, in your modifications, a
facility refers to a function or data to be supplied by an Application
that uses the facility (other than as an argument passed when the
facility is invoked), then you may convey a copy of the modified
version:
a) under this License, provided that you make a good faith effort to
ensure that, in the event an Application does not supply the
function or data, the facility still operates, and performs
whatever part of its purpose remains meaningful, or
b) under the GNU GPL, with none of the additional permissions of
this License applicable to that copy.
3. Object Code Incorporating Material from Library Header Files.
The object code form of an Application may incorporate material from
a header file that is part of the Library. You may convey such object
code under terms of your choice, provided that, if the incorporated
material is not limited to numerical parameters, data structure
layouts and accessors, or small macros, inline functions and templates
(ten or fewer lines in length), you do both of the following:
a) Give prominent notice with each copy of the object code that the
Library is used in it and that the Library and its use are
covered by this License.
b) Accompany the object code with a copy of the GNU GPL and this license
document.
4. Combined Works.
You may convey a Combined Work under terms of your choice that,
taken together, effectively do not restrict modification of the
portions of the Library contained in the Combined Work and reverse
engineering for debugging such modifications, if you also do each of
the following:
a) Give prominent notice with each copy of the Combined Work that
the Library is used in it and that the Library and its use are
covered by this License.
b) Accompany the Combined Work with a copy of the GNU GPL and this license
document.
c) For a Combined Work that displays copyright notices during
execution, include the copyright notice for the Library among
these notices, as well as a reference directing the user to the
copies of the GNU GPL and this license document.
d) Do one of the following:
0) Convey the Minimal Corresponding Source under the terms of this
License, and the Corresponding Application Code in a form
suitable for, and under terms that permit, the user to
recombine or relink the Application with a modified version of
the Linked Version to produce a modified Combined Work, in the
manner specified by section 6 of the GNU GPL for conveying
Corresponding Source.
1) Use a suitable shared library mechanism for linking with the
Library. A suitable mechanism is one that (a) uses at run time
a copy of the Library already present on the user's computer
system, and (b) will operate properly with a modified version
of the Library that is interface-compatible with the Linked
Version.
e) Provide Installation Information, but only if you would otherwise
be required to provide such information under section 6 of the
GNU GPL, and only to the extent that such information is
necessary to install and execute a modified version of the
Combined Work produced by recombining or relinking the
Application with a modified version of the Linked Version. (If
you use option 4d0, the Installation Information must accompany
the Minimal Corresponding Source and Corresponding Application
Code. If you use option 4d1, you must provide the Installation
Information in the manner specified by section 6 of the GNU GPL
for conveying Corresponding Source.)
5. Combined Libraries.
You may place library facilities that are a work based on the
Library side by side in a single library together with other library
facilities that are not Applications and are not covered by this
License, and convey such a combined library under terms of your
choice, if you do both of the following:
a) Accompany the combined library with a copy of the same work based
on the Library, uncombined with any other library facilities,
conveyed under the terms of this License.
b) Give prominent notice with the combined library that part of it
is a work based on the Library, and explaining where to find the
accompanying uncombined form of the same work.
6. Revised Versions of the GNU Lesser General Public License.
The Free Software Foundation may publish revised and/or new versions
of the GNU Lesser General Public License from time to time. Such new
versions will be similar in spirit to the present version, but may
differ in detail to address new problems or concerns.
Each version is given a distinguishing version number. If the
Library as you received it specifies that a certain numbered version
of the GNU Lesser General Public License "or any later version"
applies to it, you have the option of following the terms and
conditions either of that published version or of any later version
published by the Free Software Foundation. If the Library as you
received it does not specify a version number of the GNU Lesser
General Public License, you may choose any version of the GNU Lesser
General Public License ever published by the Free Software Foundation.
If the Library as you received it specifies that a proxy can decide
whether future versions of the GNU Lesser General Public License shall
apply, that proxy's public statement of acceptance of any version is
permanent authorization for you to choose that version for the
Library.

View File

@ -0,0 +1,214 @@
<?xml version="1.0" encoding="utf-8"?>
<Project DefaultTargets="Build" ToolsVersion="15.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<ItemGroup Label="ProjectConfigurations">
<ProjectConfiguration Include="Debug|Win32">
<Configuration>Debug</Configuration>
<Platform>Win32</Platform>
</ProjectConfiguration>
<ProjectConfiguration Include="Debug|x64">
<Configuration>Debug</Configuration>
<Platform>x64</Platform>
</ProjectConfiguration>
<ProjectConfiguration Include="Release|Win32">
<Configuration>Release</Configuration>
<Platform>Win32</Platform>
</ProjectConfiguration>
<ProjectConfiguration Include="Release|x64">
<Configuration>Release</Configuration>
<Platform>x64</Platform>
</ProjectConfiguration>
</ItemGroup>
<PropertyGroup Label="Globals">
<ProjectGuid>{1433EC85-BDA4-402E-BEC1-48611206A64A}</ProjectGuid>
<Keyword>QtVS_v302</Keyword>
<WindowsTargetPlatformVersion>8.1</WindowsTargetPlatformVersion>
<QtMsBuild Condition="'$(QtMsBuild)'=='' OR !Exists('$(QtMsBuild)\qt.targets')">$(MSBuildProjectDirectory)\QtMsBuild</QtMsBuild>
</PropertyGroup>
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" />
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'" Label="Configuration">
<ConfigurationType>DynamicLibrary</ConfigurationType>
<PlatformToolset>v140</PlatformToolset>
<SpectreMitigation>false</SpectreMitigation>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'" Label="Configuration">
<ConfigurationType>DynamicLibrary</ConfigurationType>
<PlatformToolset>v141</PlatformToolset>
<SpectreMitigation>false</SpectreMitigation>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'" Label="Configuration">
<ConfigurationType>DynamicLibrary</ConfigurationType>
<PlatformToolset>v141</PlatformToolset>
<SpectreMitigation>false</SpectreMitigation>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'" Label="Configuration">
<ConfigurationType>DynamicLibrary</ConfigurationType>
<PlatformToolset>v141</PlatformToolset>
<SpectreMitigation>false</SpectreMitigation>
</PropertyGroup>
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" />
<Target Name="QtMsBuildNotFound" BeforeTargets="CustomBuild;ClCompile" Condition="!Exists('$(QtMsBuild)\qt.targets') or !Exists('$(QtMsBuild)\qt.props')">
<Message Importance="High" Text="QtMsBuild: could not locate qt.targets, qt.props; project may not build correctly." />
</Target>
<ImportGroup Label="ExtensionSettings" />
<ImportGroup Label="Shared" />
<ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
</ImportGroup>
<ImportGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'" Label="PropertySheets">
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
</ImportGroup>
<ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
</ImportGroup>
<ImportGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'" Label="PropertySheets">
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
</ImportGroup>
<PropertyGroup Label="UserMacros" />
<ImportGroup Condition="Exists('$(QtMsBuild)\qt_defaults.props')">
<Import Project="$(QtMsBuild)\qt_defaults.props" />
</ImportGroup>
<PropertyGroup Label="QtSettings" Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
<QtInstall>msvc2015_64</QtInstall>
<QtModules>core</QtModules>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'" Label="QtSettings">
<QtInstall>msvc2015_64</QtInstall>
<QtModules>core</QtModules>
</PropertyGroup>
<PropertyGroup Label="QtSettings" Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
<QtInstall>msvc2015_64</QtInstall>
<QtModules>core</QtModules>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'" Label="QtSettings">
<QtInstall>msvc2015_64</QtInstall>
<QtModules>core</QtModules>
</PropertyGroup>
<ImportGroup Condition="Exists('$(QtMsBuild)\qt.props')">
<Import Project="$(QtMsBuild)\qt.props" />
</ImportGroup>
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
<QtMoc>
<PrependInclude>stdafx.h</PrependInclude>
</QtMoc>
<ClCompile>
<MultiProcessorCompilation>true</MultiProcessorCompilation>
<Optimization>Disabled</Optimization>
<DebugInformationFormat>ProgramDatabase</DebugInformationFormat>
<RuntimeLibrary>MultiThreadedDebugDLL</RuntimeLibrary>
<TreatWChar_tAsBuiltInType>true</TreatWChar_tAsBuiltInType>
<PrecompiledHeader>Use</PrecompiledHeader>
<PrecompiledHeaderFile>stdafx.h</PrecompiledHeaderFile>
<PrecompiledHeaderOutputFile>$(IntDir)$(TargetName).pch</PrecompiledHeaderOutputFile>
<PreprocessorDefinitions>QSBIEAPI_LIB;%(PreprocessorDefinitions)</PreprocessorDefinitions>
<AdditionalIncludeDirectories>.;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
</ClCompile>
<Link>
<SubSystem>Windows</SubSystem>
<OutputFile>$(OutDir)\$(ProjectName).dll</OutputFile>
<GenerateDebugInformation>true</GenerateDebugInformation>
<AdditionalDependencies>ntdll.lib;%(AdditionalDependencies)</AdditionalDependencies>
</Link>
</ItemDefinitionGroup>
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
<QtMoc>
<PrependInclude>stdafx.h</PrependInclude>
</QtMoc>
<ClCompile>
<MultiProcessorCompilation>true</MultiProcessorCompilation>
<Optimization>Disabled</Optimization>
<DebugInformationFormat>ProgramDatabase</DebugInformationFormat>
<RuntimeLibrary>MultiThreadedDebugDLL</RuntimeLibrary>
<TreatWChar_tAsBuiltInType>true</TreatWChar_tAsBuiltInType>
<PrecompiledHeader>Use</PrecompiledHeader>
<PrecompiledHeaderFile>stdafx.h</PrecompiledHeaderFile>
<PrecompiledHeaderOutputFile>$(IntDir)$(TargetName).pch</PrecompiledHeaderOutputFile>
<PreprocessorDefinitions>QSBIEAPI_LIB;UNICODE;_UNICODE;WIN32;WIN64;%(PreprocessorDefinitions)</PreprocessorDefinitions>
<AdditionalIncludeDirectories>.;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
</ClCompile>
<Link>
<SubSystem>Windows</SubSystem>
<OutputFile>$(OutDir)\$(ProjectName).dll</OutputFile>
<GenerateDebugInformation>true</GenerateDebugInformation>
<TargetMachine>MachineX86</TargetMachine>
<AdditionalOptions> /SUBSYSTEM:WINDOWS</AdditionalOptions>
</Link>
</ItemDefinitionGroup>
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
<QtMoc>
<PrependInclude>stdafx.h</PrependInclude>
</QtMoc>
<ClCompile>
<MultiProcessorCompilation>true</MultiProcessorCompilation>
<DebugInformationFormat />
<RuntimeLibrary>MultiThreadedDLL</RuntimeLibrary>
<TreatWChar_tAsBuiltInType>true</TreatWChar_tAsBuiltInType>
<PrecompiledHeader>Use</PrecompiledHeader>
<PrecompiledHeaderFile>stdafx.h</PrecompiledHeaderFile>
<PrecompiledHeaderOutputFile>$(IntDir)$(TargetName).pch</PrecompiledHeaderOutputFile>
<PreprocessorDefinitions>QSBIEAPI_LIB;%(PreprocessorDefinitions)</PreprocessorDefinitions>
<AdditionalIncludeDirectories>.;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
</ClCompile>
<Link>
<SubSystem>Windows</SubSystem>
<OutputFile>$(OutDir)\$(ProjectName).dll</OutputFile>
<GenerateDebugInformation>false</GenerateDebugInformation>
<AdditionalDependencies>ntdll.lib;%(AdditionalDependencies)</AdditionalDependencies>
</Link>
</ItemDefinitionGroup>
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
<QtMoc>
<PrependInclude>stdafx.h</PrependInclude>
</QtMoc>
<ClCompile>
<MultiProcessorCompilation>true</MultiProcessorCompilation>
<DebugInformationFormat>
</DebugInformationFormat>
<RuntimeLibrary>MultiThreadedDLL</RuntimeLibrary>
<TreatWChar_tAsBuiltInType>true</TreatWChar_tAsBuiltInType>
<PrecompiledHeader>Use</PrecompiledHeader>
<PrecompiledHeaderFile>stdafx.h</PrecompiledHeaderFile>
<PrecompiledHeaderOutputFile>$(IntDir)$(TargetName).pch</PrecompiledHeaderOutputFile>
<PreprocessorDefinitions>QSBIEAPI_LIB;UNICODE;_UNICODE;WIN32;WIN64;%(PreprocessorDefinitions)</PreprocessorDefinitions>
<AdditionalIncludeDirectories>.;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
</ClCompile>
<Link>
<SubSystem>Windows</SubSystem>
<OutputFile>$(OutDir)\$(ProjectName).dll</OutputFile>
<GenerateDebugInformation>false</GenerateDebugInformation>
<TargetMachine>MachineX86</TargetMachine>
<AdditionalOptions> /SUBSYSTEM:WINDOWS</AdditionalOptions>
</Link>
</ItemDefinitionGroup>
<ItemGroup>
<ClCompile Include="Sandboxie\BoxedProcess.cpp" />
<ClCompile Include="Sandboxie\SandBox.cpp" />
<ClCompile Include="Sandboxie\IniSection.cpp" />
<ClCompile Include="SbieAPI.cpp" />
<ClCompile Include="stdafx.cpp">
<PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">Create</PrecompiledHeader>
<PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">Create</PrecompiledHeader>
<PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Release|x64'">Create</PrecompiledHeader>
<PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">Create</PrecompiledHeader>
</ClCompile>
</ItemGroup>
<ItemGroup>
<QtMoc Include="SbieAPI.h" />
<ClInclude Include="qsbieapi_global.h" />
<QtMoc Include="Sandboxie\BoxedProcess.h" />
<QtMoc Include="Sandboxie\SandBox.h" />
<QtMoc Include="Sandboxie\IniSection.h" />
<ClInclude Include="SbieError.h" />
<ClInclude Include="stdafx.h" />
</ItemGroup>
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
<ImportGroup Condition="Exists('$(QtMsBuild)\qt.targets')">
<Import Project="$(QtMsBuild)\qt.targets" />
</ImportGroup>
<ImportGroup Label="ExtensionTargets">
</ImportGroup>
<ProjectExtensions>
<VisualStudio>
<UserProperties MocDir=".\GeneratedFiles\$(ConfigurationName)" UicDir=".\GeneratedFiles" RccDir=".\GeneratedFiles" lupdateOptions="" lupdateOnBuild="0" lreleaseOptions="" MocOptions="" />
</VisualStudio>
</ProjectExtensions>
</Project>

View File

@ -0,0 +1,73 @@
<?xml version="1.0" encoding="utf-8"?>
<Project ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<ItemGroup>
<Filter Include="Source Files">
<UniqueIdentifier>{4FC737F1-C7A5-4376-A066-2A32D752A2FF}</UniqueIdentifier>
<Extensions>cpp;c;cc;cxx;def;odl;idl;hpj;bat;asm;asmx</Extensions>
</Filter>
<Filter Include="Header Files">
<UniqueIdentifier>{93995380-89BD-4b04-88EB-625FBE52EBFB}</UniqueIdentifier>
<Extensions>h;hh;hpp;hxx;hm;inl;inc;xsd</Extensions>
</Filter>
<Filter Include="Resource Files">
<UniqueIdentifier>{D9D6E242-F8AF-46E4-B9FD-80ECBC20BA3E}</UniqueIdentifier>
<Extensions>qrc;*</Extensions>
<ParseFiles>false</ParseFiles>
</Filter>
<Filter Include="Resource Files">
<UniqueIdentifier>{D9D6E242-F8AF-46E4-B9FD-80ECBC20BA3E}</UniqueIdentifier>
<Extensions>qrc;*</Extensions>
<ParseFiles>false</ParseFiles>
</Filter>
<Filter Include="SbieAPI">
<UniqueIdentifier>{1cc5894c-f677-4167-9b99-bdc19b3ecd9d}</UniqueIdentifier>
</Filter>
<Filter Include="Sandboxie">
<UniqueIdentifier>{a34e523b-19e3-4951-b7f2-d0bcd66886d6}</UniqueIdentifier>
</Filter>
</ItemGroup>
<ItemGroup>
<ClCompile Include="stdafx.cpp">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="SbieAPI.cpp">
<Filter>SbieAPI</Filter>
</ClCompile>
<ClCompile Include="Sandboxie\BoxedProcess.cpp">
<Filter>Sandboxie</Filter>
</ClCompile>
<ClCompile Include="Sandboxie\SandBox.cpp">
<Filter>Sandboxie</Filter>
</ClCompile>
<ClCompile Include="Sandboxie\IniSection.cpp">
<Filter>Sandboxie</Filter>
</ClCompile>
</ItemGroup>
<ItemGroup>
<ClInclude Include="stdafx.h">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="SbieError.h">
<Filter>SbieAPI</Filter>
</ClInclude>
</ItemGroup>
<ItemGroup>
<ClInclude Include="qsbieapi_global.h">
<Filter>Header Files</Filter>
</ClInclude>
</ItemGroup>
<ItemGroup>
<QtMoc Include="Sandboxie\BoxedProcess.h">
<Filter>Sandboxie</Filter>
</QtMoc>
<QtMoc Include="Sandboxie\SandBox.h">
<Filter>Sandboxie</Filter>
</QtMoc>
<QtMoc Include="SbieAPI.h">
<Filter>SbieAPI</Filter>
</QtMoc>
<QtMoc Include="Sandboxie\IniSection.h">
<Filter>Sandboxie</Filter>
</QtMoc>
</ItemGroup>
</Project>

View File

@ -0,0 +1,4 @@
<?xml version="1.0" encoding="utf-8"?>
<Project ToolsVersion="15.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<PropertyGroup />
</Project>

View File

@ -0,0 +1,156 @@
/*
*
* Copyright (c) 2020, David Xanatos
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2.1 of the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#include "stdafx.h"
#include "BoxedProcess.h"
#include "SandBox.h"
#include "../SbieAPI.h"
#include <ntstatus.h>
#define WIN32_NO_STATUS
typedef long NTSTATUS;
#include <windows.h>
#include "..\..\Sandboxie\common\win32_ntddk.h"
#include <psapi.h> // For access to GetModuleFileNameEx
//struct SBoxedProcess
//{
//};
CBoxedProcess::CBoxedProcess(quint64 ProcessId, class CSandBox* pBox)
{
m_pBox = pBox;
//m = new SBoxedProcess;
m_ProcessId = ProcessId;
m_ParendPID = 0;
m_SessionId = 0;
m_bTerminated = false;
m_bSuspended = IsSuspended();
}
CBoxedProcess::~CBoxedProcess()
{
//delete m;
}
void CBoxedProcess::UpdateProcessInfo()
{
HANDLE ProcessHandle = OpenProcess(PROCESS_QUERY_INFORMATION | PROCESS_VM_READ, FALSE, (DWORD)m_ProcessId);
if (ProcessHandle != INVALID_HANDLE_VALUE)
{
PROCESS_BASIC_INFORMATION BasicInformation;
NTSTATUS status = NtQueryInformationProcess(ProcessHandle, ProcessBasicInformation, &BasicInformation, sizeof(PROCESS_BASIC_INFORMATION), NULL);
if (NT_SUCCESS(status)) {
m_ParendPID = (quint64)BasicInformation.InheritedFromUniqueProcessId;
}
TCHAR filename[MAX_PATH];
if (DWORD size = GetModuleFileNameEx(ProcessHandle, NULL, filename, MAX_PATH))
m_ImagePath = QString::fromWCharArray(filename);
NtClose(ProcessHandle);
}
}
QString CBoxedProcess::GetStatusStr() const
{
if (m_bTerminated)
return tr("Terminated");
if (m_bSuspended)
return tr("Suspended");
return tr("Running");
}
extern "C"
{
NTSYSCALLAPI NTSTATUS NTAPI NtTerminateProcess(_In_opt_ HANDLE ProcessHandle, _In_ NTSTATUS ExitStatus);
NTSYSCALLAPI NTSTATUS NTAPI NtSuspendProcess(_In_ HANDLE ProcessHandle);
NTSYSCALLAPI NTSTATUS NTAPI NtResumeProcess(_In_ HANDLE ProcessHandle);
}
#include <TlHelp32.h>
SB_STATUS CBoxedProcess::Terminate()
{
return m_pBox->Api()->Terminate(m_ProcessId);
}
SB_STATUS CBoxedProcess::SetSuspend(bool bSet)
{
HANDLE ProcessHandle = OpenProcess(PROCESS_SUSPEND_RESUME, FALSE, (DWORD)m_ProcessId);
if (ProcessHandle != INVALID_HANDLE_VALUE)
{
NTSTATUS status;
if(bSet)
status = NtSuspendProcess(ProcessHandle);
else
status = NtResumeProcess(ProcessHandle);
NtClose(ProcessHandle);
if (!NT_SUCCESS(status))
return SB_ERR(status);
m_bSuspended = IsSuspended();
return SB_OK;
}
return SB_ERR();
}
bool CBoxedProcess::IsSuspended() const
{
bool isSuspended = true;
// todo: do that globaly once per sec for all boxed processes
// Note: If the specified process is a 64-bit process and the caller is a 32-bit process, this function fails and the last error code is ERROR_PARTIAL_COPY (299).
HANDLE hThreadSnap = CreateToolhelp32Snapshot(TH32CS_SNAPTHREAD, 0);
if (hThreadSnap == INVALID_HANDLE_VALUE)
return false;
THREADENTRY32 te32 = { 0 };
te32.dwSize = sizeof(THREADENTRY32);
if (Thread32First(hThreadSnap, &te32))
{
do
{
if (te32.th32OwnerProcessID != m_ProcessId)
continue;
HANDLE hThread = OpenThread(THREAD_QUERY_INFORMATION, FALSE, te32.th32ThreadID);
ULONG SuspendCount = 0;
NTSTATUS status = NtQueryInformationThread(hThread, (THREADINFOCLASS)35/*ThreadSuspendCount*/, &SuspendCount, sizeof(ULONG), NULL);
CloseHandle(hThread);
if (SuspendCount == 0)
{
isSuspended = false;
break;
}
} while (Thread32Next(hThreadSnap, &te32));
}
CloseHandle(hThreadSnap);
return isSuspended;
}

View File

@ -0,0 +1,66 @@
/*
*
* Copyright (c) 2020, David Xanatos
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2.1 of the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#pragma once
#include <qobject.h>
#include "../SbieError.h"
class CBoxedProcess : public QObject
{
Q_OBJECT
public:
CBoxedProcess(quint64 ProcessId, class CSandBox* pBox);
virtual ~CBoxedProcess();
virtual void UpdateProcessInfo();
virtual quint64 GetProcessId() const { return m_ProcessId; }
virtual quint64 GetParendPID() const { return m_ParendPID; }
virtual QString GetProcessName() const { return m_ImageName; }
virtual QString GetFileName() const { return m_ImagePath; }
virtual QDateTime GetTimeStamp() const { return m_StartTime; }
virtual QString GetStatusStr() const;
virtual SB_STATUS Terminate();
virtual bool IsTerminated() const { return m_bTerminated; }
virtual void SetTerminated() { m_bTerminated = true; }
virtual SB_STATUS SetSuspend(bool bSet);
virtual bool IsSuspended() const;
protected:
friend class CSbieAPI;
quint64 m_ProcessId;
quint64 m_ParendPID;
QString m_ImageName;
QString m_ImagePath;
quint32 m_SessionId;
QDateTime m_StartTime;
bool m_bTerminated;
bool m_bSuspended;
class CSandBox* m_pBox;
//private:
// struct SBoxedProcess* m;
};
typedef QSharedPointer<CBoxedProcess> CBoxedProcessPtr;
typedef QWeakPointer<CBoxedProcess> CBoxedProcessRef;

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