first commit
Version 3.x.x
125
.gitignore
vendored
Normal file
@ -0,0 +1,125 @@
|
|||||||
|
bin/**
|
||||||
|
tmp/**
|
||||||
|
*.suo
|
||||||
|
xcuserdata
|
||||||
|
.DS_Store
|
||||||
|
/.klocwork
|
||||||
|
/ipch
|
||||||
|
/VMProtect/moc
|
||||||
|
*.user
|
||||||
|
VMProtectSDK32.def
|
||||||
|
VMProtectSDK64.def
|
||||||
|
build.log
|
||||||
|
*.dylib
|
||||||
|
*.dll
|
||||||
|
*.sys
|
||||||
|
vmprotect.opensdf
|
||||||
|
vmprotect.sdf
|
||||||
|
core/version.h
|
||||||
|
*.aps
|
||||||
|
core/lang.tmp
|
||||||
|
core/lang.inc
|
||||||
|
*.log
|
||||||
|
/iss/Output
|
||||||
|
*.tmp
|
||||||
|
*.vsp
|
||||||
|
*.vspx
|
||||||
|
*.psess
|
||||||
|
/iss/end_user/Output
|
||||||
|
*.hmap
|
||||||
|
*.dcu
|
||||||
|
/iss/keygen/__history
|
||||||
|
/third-party/diskid/Debug
|
||||||
|
/third-party/diskid/Release
|
||||||
|
/third-party/diskid/x64/Release
|
||||||
|
/third-party/diskid/x64/Debug
|
||||||
|
/third-party/taggant/java_pkiclient/lib
|
||||||
|
/third-party/taggant/java_pkiclient/pkiwebserviceclient.jar
|
||||||
|
/Debug
|
||||||
|
/third-party/diskid/.klocwork/diskid
|
||||||
|
ConsoleApplication1/
|
||||||
|
utils/bc/
|
||||||
|
iss/end_user/NoSend/
|
||||||
|
TestResults/
|
||||||
|
third-party/.klocwork/
|
||||||
|
unit-tests/.klocwork/
|
||||||
|
sdk/VMProtect.SDK/obj/
|
||||||
|
utils/ipn_sqlclr/obj/
|
||||||
|
unit-tests/ipn_sqlclr.Test/bin/
|
||||||
|
utils/.klocwork/
|
||||||
|
utils/ipn_sqlclr/.klocwork/
|
||||||
|
examples/dotnet/forms_mixed/Debug/
|
||||||
|
examples/dotnet/forms_mixed/Release/
|
||||||
|
iss/end_user/Ban/
|
||||||
|
examples/dotnet/.klocwork/
|
||||||
|
examples/dotnet/ConsoleApplication2/.klocwork/
|
||||||
|
third-party/taggant/java_pkiclient/portecle-1.7/
|
||||||
|
utils/ipn_sqlclr/bin/
|
||||||
|
unit-tests/ipn_sqlclr.Test/obj/
|
||||||
|
utils/ipn_tool/bin/
|
||||||
|
core/lang_def.inc
|
||||||
|
core/lang_enum.inc
|
||||||
|
core/lang_info.inc
|
||||||
|
examples/dotnet/Debug/
|
||||||
|
mac_commond.mak
|
||||||
|
VMProtect/resources.cc
|
||||||
|
VMProtect/mac_guid.mak
|
||||||
|
VMProtect/mac_gui64_debug.mak
|
||||||
|
iss/keygen/Project1.dproj.local
|
||||||
|
core/mac_cored.mak
|
||||||
|
core/mac_core64_debug.mak
|
||||||
|
core/invariant/mac_invariant_cored.mak
|
||||||
|
core/invariant/mac_invariant_core64_debug.mak
|
||||||
|
app/vmprotect_gui.app/Contents/Info.plist
|
||||||
|
utils/ipn_tool/obj/
|
||||||
|
utils/ipn_sqlclr/ipn_sqlclr.publish.xml
|
||||||
|
utils/ipn_sqlclr/ipn_sqlclr.sln
|
||||||
|
examples/dotnet/forms_cil/bin/
|
||||||
|
examples/dotnet/forms_cil/obj/
|
||||||
|
examples/dotnet/ConsoleApplication2/
|
||||||
|
examples/dotnet/ConsoleApplication3/
|
||||||
|
examples/code markers/Xcode/Build/
|
||||||
|
examples/code markers/Xcode/Project1.xcodeproj/project.xcworkspace/xcshareddata/
|
||||||
|
examples/code markers/Xcode/Project1/VMProtectSDK.h
|
||||||
|
examples/licensing/Xcode/VMProtectSDK.h
|
||||||
|
examples/licensing/Xcode/VMProtect Licensing Test.xcodeproj/project.xcworkspace/xcshareddata/
|
||||||
|
examples/licensing/Xcode/Build/
|
||||||
|
third-party/taggant/java_pkiclient/stuff/certificates/
|
||||||
|
third-party/taggant/java_pkiclient/check/
|
||||||
|
third-party/taggant/java_pkiclient/root.p7b
|
||||||
|
third-party/taggant/java_pkiclient/lic.pem
|
||||||
|
third-party/taggant/java_pkiclient/gp.txt
|
||||||
|
third-party/taggant/java_pkiclient/exp_pki_ra.cer
|
||||||
|
third-party/taggant/java_pkiclient/client.p12
|
||||||
|
third-party/taggant/java_pkiclient/VMP.cer
|
||||||
|
*.FileListAbsolute.txt
|
||||||
|
third-party/crashrpt/
|
||||||
|
runtime/VMProtect.Runtime/Tests/UnitTestProject/bin/
|
||||||
|
runtime/VMProtect.Runtime/Tests/UnitTestProject/obj/
|
||||||
|
test-binaries/win32-app-delphi-i386.exe
|
||||||
|
test-binaries/win32-app-test1-i386.exe
|
||||||
|
test-binaries/win64-app-msvc-amd64.exe
|
||||||
|
vmprotect.VC.VC.opendb
|
||||||
|
vmprotect.VC.db
|
||||||
|
runtime/VMProtect.Runtime/obj/
|
||||||
|
*.opendb
|
||||||
|
*.db
|
||||||
|
*.ipch
|
||||||
|
examples/licensing/Net/bin/
|
||||||
|
examples/licensing/Net/obj/
|
||||||
|
examples/licensing/MSVC/bin/
|
||||||
|
examples/licensing/MSVC/tmp/
|
||||||
|
examples/licensing/MSVC/VMProtectSDK.h
|
||||||
|
examples/licensing/MSVC/VMProtectSDK32.lib
|
||||||
|
examples/licensing/C#/VMProtect.SDK.pdb
|
||||||
|
VMProtect.SDK.pdb
|
||||||
|
examples/code markers/Net/bin/
|
||||||
|
examples/code markers/Net/obj/
|
||||||
|
examples/keygen/Net/KeyGen/obj/
|
||||||
|
examples/keygen/Net/bin/
|
||||||
|
third-party/taggant/openssl/ms/Debug/
|
||||||
|
*.so
|
||||||
|
*.exe
|
||||||
|
/iss/body.txt
|
||||||
|
/iss/ipn/vmprotect.vmp
|
||||||
|
/iss/ipn/licenses/
|
17
NetX64.testsettings
Normal file
@ -0,0 +1,17 @@
|
|||||||
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
|
<TestSettings name="TestSettingsNetX64" id="20a4f799-7d31-4678-a2b9-79cdf7b1e821" xmlns="http://microsoft.com/schemas/VisualStudio/TeamTest/2010">
|
||||||
|
<Description>These are default test settings for a local test run.</Description>
|
||||||
|
<Deployment enabled="false" />
|
||||||
|
<Execution hostProcessPlatform="MSIL">
|
||||||
|
<TestTypeSpecific>
|
||||||
|
<UnitTestRunConfig testTypeId="13cdc9d9-ddb5-4fa4-a97d-d965ccfc6d4b">
|
||||||
|
<AssemblyResolution>
|
||||||
|
<TestDirectory useLoadContext="true" />
|
||||||
|
</AssemblyResolution>
|
||||||
|
</UnitTestRunConfig>
|
||||||
|
</TestTypeSpecific>
|
||||||
|
<AgentRule name="Execution Agents">
|
||||||
|
</AgentRule>
|
||||||
|
</Execution>
|
||||||
|
<Properties />
|
||||||
|
</TestSettings>
|
9
NetX86.testsettings
Normal file
@ -0,0 +1,9 @@
|
|||||||
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
|
<TestSettings
|
||||||
|
id="fe7fee5f-a8df-4e00-90e9-1e11936b044a"
|
||||||
|
name="NetX86"
|
||||||
|
enableDefaultDataCollectors="false"
|
||||||
|
xmlns="http://microsoft.com/schemas/VisualStudio/TeamTest/2010">
|
||||||
|
<Description><!--_locID_text="Description1"-->These are default test settings for a local test run.</Description>
|
||||||
|
<Deployment enabled="false" />
|
||||||
|
</TestSettings>
|
4
New Text Document.txt
Normal file
@ -0,0 +1,4 @@
|
|||||||
|
需要修复:
|
||||||
|
|
||||||
|
_CxxThrowException
|
||||||
|
返回地址必须填充Nop否则会出错
|
10
README
Normal file
@ -0,0 +1,10 @@
|
|||||||
|
VMProtect project
|
||||||
|
-----------------
|
||||||
|
|
||||||
|
Building
|
||||||
|
|
||||||
|
POSIX:
|
||||||
|
$ ./build.sh
|
||||||
|
|
||||||
|
Windows:
|
||||||
|
> build.bat
|
177
VMProtect/about_dialog.cc
Normal file
@ -0,0 +1,177 @@
|
|||||||
|
#include "../core/objects.h"
|
||||||
|
#include "../core/files.h"
|
||||||
|
#include "../core/core.h"
|
||||||
|
#include "../core/lang.h"
|
||||||
|
#include "widgets.h"
|
||||||
|
#include "about_dialog.h"
|
||||||
|
#include "help_browser.h"
|
||||||
|
#include "moc/moc_about_dialog.cc"
|
||||||
|
|
||||||
|
/**
|
||||||
|
* AboutDialog
|
||||||
|
*/
|
||||||
|
|
||||||
|
AboutDialog::AboutDialog(QWidget *parent)
|
||||||
|
: QDialog(parent, Qt::WindowSystemMenuHint | Qt::WindowTitleHint | Qt::CustomizeWindowHint | Qt::WindowCloseButtonHint | Qt::MSWindowsFixedSizeDialogHint)
|
||||||
|
{
|
||||||
|
setWindowTitle(QString::fromUtf8(language[lsAbout].c_str()));
|
||||||
|
|
||||||
|
QAction *helpAction = new QAction(this);
|
||||||
|
helpAction->setShortcut(HelpContentsKeySequence());
|
||||||
|
connect(helpAction, SIGNAL(triggered()), this, SLOT(help()));
|
||||||
|
|
||||||
|
addAction(helpAction);
|
||||||
|
|
||||||
|
QFrame *top = new QFrame(this);
|
||||||
|
top->setObjectName("bootTop");
|
||||||
|
|
||||||
|
QLabel *logo = new QLabel(this);
|
||||||
|
logo->setPixmap(QPixmap(":/images/logo.png"));
|
||||||
|
|
||||||
|
QLabel *version = new QLabel(QString::fromLatin1(Core::edition()) + " v " + QString::fromLatin1(Core::version()), this);
|
||||||
|
version->setObjectName("version");
|
||||||
|
|
||||||
|
QLabel *build = new QLabel("build " + QString::fromLatin1(Core::build()), this);
|
||||||
|
build->setObjectName("build");
|
||||||
|
|
||||||
|
QGridLayout *grid_layout = new QGridLayout();
|
||||||
|
grid_layout->setContentsMargins(30, 30, 30, 20);
|
||||||
|
grid_layout->setSpacing(0);
|
||||||
|
grid_layout->setColumnStretch(1, 1);
|
||||||
|
grid_layout->addWidget(logo, 0, 0, 3, 1);
|
||||||
|
grid_layout->addWidget(version, 0, 1, Qt::AlignCenter);
|
||||||
|
grid_layout->addItem(new QSpacerItem(0, 0, QSizePolicy::Expanding, QSizePolicy::Expanding), 1, 1);
|
||||||
|
grid_layout->addWidget(build, 2, 1, Qt::AlignRight);
|
||||||
|
top->setLayout(grid_layout);
|
||||||
|
|
||||||
|
QFrame *line1 = new QFrame(this);
|
||||||
|
line1->setObjectName("bootHSeparator");
|
||||||
|
line1->setFixedHeight(1);
|
||||||
|
|
||||||
|
QFrame *center = new QFrame(this);
|
||||||
|
center->setObjectName("boot");
|
||||||
|
|
||||||
|
QLabel *registered1 = new QLabel(this);
|
||||||
|
registered1->setWordWrap(true);
|
||||||
|
QLabel *registered2 = new QLabel(this);
|
||||||
|
registered2->setWordWrap(true);
|
||||||
|
|
||||||
|
enum PurchaseMode {
|
||||||
|
pmLicense,
|
||||||
|
pmSubscriptionPersonal,
|
||||||
|
pmSubscriptionCompany
|
||||||
|
};
|
||||||
|
|
||||||
|
QPushButton *purchase = NULL;
|
||||||
|
PurchaseMode purchaseMode = pmLicense;
|
||||||
|
#ifdef DEMO
|
||||||
|
registered1->setText(QString::fromUtf8(language[lsDemoVersion].c_str()));
|
||||||
|
registered1->setObjectName("unregistered");
|
||||||
|
|
||||||
|
purchase = new PushButton(QString::fromUtf8(language[lsPurchaseLicense].c_str()), this);
|
||||||
|
#else
|
||||||
|
VMProtectSerialNumberData data;
|
||||||
|
data.nState = SERIAL_STATE_FLAG_INVALID;
|
||||||
|
if (VMProtectGetSerialNumberData(&data, sizeof(data)) && data.nState == 0) {
|
||||||
|
registered1->setText(QString("%1: <b>%2 [%3], %4</b>").arg(QString::fromUtf8(language[lsRegisteredTo].c_str())).
|
||||||
|
arg(QString::fromUtf16((ushort *)data.wUserName)).
|
||||||
|
arg(QString::fromUtf16((ushort *)data.wEMail)).
|
||||||
|
arg((data.bUserData[0] & 1) ? "Personal License" : "Company License"));
|
||||||
|
if (data.dtMaxBuild.wYear) {
|
||||||
|
QDate dt = QDate(data.dtMaxBuild.wYear, data.dtMaxBuild.bMonth, data.dtMaxBuild.bDay);
|
||||||
|
registered2->setText(QString("%1: <b>%2</b>").arg(QString::fromUtf8(language[lsFreeUpdatesPeriod].c_str())).arg(dt.toString(Qt::SystemLocaleShortDate)));
|
||||||
|
|
||||||
|
if (QDate::currentDate() > dt) {
|
||||||
|
purchase = new PushButton(QString::fromUtf8(language[lsPurchaseSubscription].c_str()), this);
|
||||||
|
if (data.nUserDataLength)
|
||||||
|
purchaseMode = (data.bUserData[0] & 1) ? pmSubscriptionPersonal : pmSubscriptionCompany;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
if (data.nState & SERIAL_STATE_FLAG_BLACKLISTED) {
|
||||||
|
registered1->setText(QString::fromLatin1(VMProtectDecryptStringA("Your key file is blocked!")));
|
||||||
|
// don't show "buy now" button
|
||||||
|
} else if (data.nState & SERIAL_STATE_FLAG_MAX_BUILD_EXPIRED) {
|
||||||
|
registered1->setText(QString::fromLatin1(VMProtectDecryptStringA("Your key file will not work with this version of VMProtect!\nYou should use older version or buy one more year of updates and technical support.")));
|
||||||
|
purchase = new PushButton(QString::fromUtf8(language[lsPurchaseSubscription].c_str()), this);
|
||||||
|
if (data.nUserDataLength)
|
||||||
|
purchaseMode = (data.bUserData[0] & 1) ? pmSubscriptionPersonal : pmSubscriptionCompany;
|
||||||
|
} else {
|
||||||
|
registered1->setText(QString::fromUtf8(language[lsUnregisteredVersion].c_str()));
|
||||||
|
purchase = new PushButton(QString::fromUtf8(language[lsPurchaseLicense].c_str()), this);
|
||||||
|
}
|
||||||
|
registered1->setObjectName("unregistered");
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
QBoxLayout *layout = new QVBoxLayout();
|
||||||
|
layout->setContentsMargins(10, 10, 10, 10);
|
||||||
|
layout->setSpacing(5);
|
||||||
|
layout->addWidget(registered1);
|
||||||
|
layout->addWidget(registered2);
|
||||||
|
layout->addStretch(1);
|
||||||
|
if (purchase) {
|
||||||
|
switch (purchaseMode) {
|
||||||
|
case pmSubscriptionPersonal:
|
||||||
|
connect(purchase, SIGNAL(clicked()), this, SLOT(purchaseSubscriptionPersonal()));
|
||||||
|
break;
|
||||||
|
case pmSubscriptionCompany:
|
||||||
|
connect(purchase, SIGNAL(clicked()), this, SLOT(purchaseSubscriptionCompany()));
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
connect(purchase, SIGNAL(clicked()), this, SLOT(purchaseLicense()));
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
layout->addWidget(purchase, 0, Qt::AlignCenter);
|
||||||
|
}
|
||||||
|
center->setLayout(layout);
|
||||||
|
|
||||||
|
QFrame *line2 = new QFrame(this);
|
||||||
|
line2->setObjectName("bootHSeparator");
|
||||||
|
line2->setFixedHeight(1);
|
||||||
|
|
||||||
|
QLabel *copyright = new QLabel(QString::fromLatin1(Core::copyright()), this);
|
||||||
|
copyright->setObjectName("copyright");
|
||||||
|
|
||||||
|
QFrame *bottom = new QFrame(this);
|
||||||
|
bottom->setObjectName("bootTop");
|
||||||
|
layout = new QHBoxLayout();
|
||||||
|
layout->setContentsMargins(10, 10, 10, 10);
|
||||||
|
layout->setSpacing(0);
|
||||||
|
layout->addWidget(copyright, 0, Qt::AlignCenter);
|
||||||
|
bottom->setLayout(layout);
|
||||||
|
|
||||||
|
layout = new QVBoxLayout();
|
||||||
|
layout->setContentsMargins(0, 0, 0, 0);
|
||||||
|
layout->setSpacing(0);
|
||||||
|
layout->addWidget(top);
|
||||||
|
layout->addWidget(line1);
|
||||||
|
layout->addWidget(center, 1);
|
||||||
|
layout->addWidget(line2);
|
||||||
|
layout->addWidget(bottom);
|
||||||
|
setLayout(layout);
|
||||||
|
|
||||||
|
setMinimumSize(500, 300);
|
||||||
|
setMaximumSize(500, 300);
|
||||||
|
//auto size: layout->setSizeConstraint(QLayout::SetFixedSize);
|
||||||
|
}
|
||||||
|
|
||||||
|
void AboutDialog::purchaseLicense()
|
||||||
|
{
|
||||||
|
QDesktopServices::openUrl(QUrl(VMProtectDecryptStringA("http://www.vmpsoft.com/purchase/buy-online/")));
|
||||||
|
}
|
||||||
|
|
||||||
|
void AboutDialog::purchaseSubscriptionPersonal()
|
||||||
|
{
|
||||||
|
QDesktopServices::openUrl(QUrl("https://store.payproglobal.com/checkout?products[1][id]=35518"));
|
||||||
|
}
|
||||||
|
|
||||||
|
void AboutDialog::purchaseSubscriptionCompany()
|
||||||
|
{
|
||||||
|
QDesktopServices::openUrl(QUrl("https://store.payproglobal.com/checkout?products[1][id]=35531"));
|
||||||
|
}
|
||||||
|
|
||||||
|
void AboutDialog::help()
|
||||||
|
{
|
||||||
|
HelpBrowser::showTopic("contacts");
|
||||||
|
}
|
16
VMProtect/about_dialog.h
Normal file
@ -0,0 +1,16 @@
|
|||||||
|
#ifndef ABOUT_DIALOG_H
|
||||||
|
#define ABOUT_DIALOG_H
|
||||||
|
|
||||||
|
class AboutDialog : public QDialog
|
||||||
|
{
|
||||||
|
Q_OBJECT
|
||||||
|
public:
|
||||||
|
AboutDialog(QWidget *parent = NULL);
|
||||||
|
private slots:
|
||||||
|
void purchaseLicense();
|
||||||
|
void purchaseSubscriptionPersonal();
|
||||||
|
void purchaseSubscriptionCompany();
|
||||||
|
void help();
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif
|
137
VMProtect/app_icon.mm
Normal file
@ -0,0 +1,137 @@
|
|||||||
|
#include <QtGui/QIcon>
|
||||||
|
#include <AppKit/AppKit.h>
|
||||||
|
|
||||||
|
/*
|
||||||
|
Helper class that automates refernce counting for CFtypes.
|
||||||
|
After constructing the QCFType object, it can be copied like a
|
||||||
|
value-based type.
|
||||||
|
|
||||||
|
Note that you must own the object you are wrapping.
|
||||||
|
This is typically the case if you get the object from a Core
|
||||||
|
Foundation function with the word "Create" or "Copy" in it. If
|
||||||
|
you got the object from a "Get" function, either retain it or use
|
||||||
|
constructFromGet(). One exception to this rule is the
|
||||||
|
HIThemeGet*Shape functions, which in reality are "Copy" functions.
|
||||||
|
*/
|
||||||
|
template <typename T>
|
||||||
|
class QCFType
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
inline QCFType(const T &t = 0) : type(t) {}
|
||||||
|
inline QCFType(const QCFType &helper) : type(helper.type) { if (type) CFRetain(type); }
|
||||||
|
inline ~QCFType() { if (type) CFRelease(type); }
|
||||||
|
inline operator T() { return type; }
|
||||||
|
inline QCFType operator =(const QCFType &helper)
|
||||||
|
{
|
||||||
|
if (helper.type)
|
||||||
|
CFRetain(helper.type);
|
||||||
|
CFTypeRef type2 = type;
|
||||||
|
type = helper.type;
|
||||||
|
if (type2)
|
||||||
|
CFRelease(type2);
|
||||||
|
return *this;
|
||||||
|
}
|
||||||
|
inline T *operator&() { return &type; }
|
||||||
|
template <typename X> X as() const { return reinterpret_cast<X>(type); }
|
||||||
|
static QCFType constructFromGet(const T &t)
|
||||||
|
{
|
||||||
|
CFRetain(t);
|
||||||
|
return QCFType<T>(t);
|
||||||
|
}
|
||||||
|
protected:
|
||||||
|
T type;
|
||||||
|
};
|
||||||
|
|
||||||
|
CGColorSpaceRef qt_mac_genericColorSpace()
|
||||||
|
{
|
||||||
|
CGDirectDisplayID displayID = CGMainDisplayID();
|
||||||
|
CGColorSpaceRef colorSpace = CGDisplayCopyColorSpace(displayID);
|
||||||
|
if (colorSpace == 0)
|
||||||
|
colorSpace = CGColorSpaceCreateDeviceRGB();
|
||||||
|
|
||||||
|
return colorSpace;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void qt_mac_deleteImage(void *image, const void *, size_t)
|
||||||
|
{
|
||||||
|
delete static_cast<QImage *>(image);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Creates a CGDataProvider with the data from the given image.
|
||||||
|
// The data provider retains a copy of the image.
|
||||||
|
CGDataProviderRef qt_mac_CGDataProvider(const QImage &image)
|
||||||
|
{
|
||||||
|
return CGDataProviderCreateWithData(new QImage(image), image.bits(),
|
||||||
|
image.byteCount(), qt_mac_deleteImage);
|
||||||
|
}
|
||||||
|
|
||||||
|
CGImageRef qt_mac_toCGImage(const QImage &inImage)
|
||||||
|
{
|
||||||
|
if (inImage.isNull())
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
QImage image = inImage;
|
||||||
|
|
||||||
|
uint cgflags = kCGImageAlphaNone;
|
||||||
|
switch (image.format()) {
|
||||||
|
case QImage::Format_ARGB32:
|
||||||
|
cgflags = kCGImageAlphaFirst | kCGBitmapByteOrder32Host;
|
||||||
|
break;
|
||||||
|
case QImage::Format_RGB32:
|
||||||
|
cgflags = kCGImageAlphaNoneSkipFirst | kCGBitmapByteOrder32Host;
|
||||||
|
break;
|
||||||
|
case QImage::Format_RGB888:
|
||||||
|
cgflags = kCGImageAlphaNone | kCGBitmapByteOrder32Big;
|
||||||
|
break;
|
||||||
|
case QImage::Format_RGBA8888_Premultiplied:
|
||||||
|
cgflags = kCGImageAlphaPremultipliedLast | kCGBitmapByteOrder32Big;
|
||||||
|
break;
|
||||||
|
case QImage::Format_RGBA8888:
|
||||||
|
cgflags = kCGImageAlphaLast | kCGBitmapByteOrder32Big;
|
||||||
|
break;
|
||||||
|
case QImage::Format_RGBX8888:
|
||||||
|
cgflags = kCGImageAlphaNoneSkipLast | kCGBitmapByteOrder32Big;
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
// Everything not recognized explicitly is converted to ARGB32_Premultiplied.
|
||||||
|
image = inImage.convertToFormat(QImage::Format_ARGB32_Premultiplied);
|
||||||
|
// no break;
|
||||||
|
case QImage::Format_ARGB32_Premultiplied:
|
||||||
|
cgflags = kCGImageAlphaPremultipliedFirst | kCGBitmapByteOrder32Host;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
QCFType<CGDataProviderRef> dataProvider = qt_mac_CGDataProvider(image);
|
||||||
|
return CGImageCreate(image.width(), image.height(), 8, 32,
|
||||||
|
image.bytesPerLine(),
|
||||||
|
qt_mac_genericColorSpace(),
|
||||||
|
cgflags, dataProvider, 0, false, kCGRenderingIntentDefault);
|
||||||
|
}
|
||||||
|
|
||||||
|
NSImage *qt_mac_create_nsimage(const QIcon &icon)
|
||||||
|
{
|
||||||
|
if (icon.isNull())
|
||||||
|
return nil;
|
||||||
|
|
||||||
|
NSImage *nsImage = [[NSImage alloc] init];
|
||||||
|
foreach (QSize size, icon.availableSizes()) {
|
||||||
|
QPixmap pm = icon.pixmap(size);
|
||||||
|
QImage image = pm.toImage();
|
||||||
|
CGImageRef cgImage = qt_mac_toCGImage(image);
|
||||||
|
NSBitmapImageRep *imageRep = [[NSBitmapImageRep alloc] initWithCGImage:cgImage];
|
||||||
|
[nsImage addRepresentation:imageRep];
|
||||||
|
[imageRep release];
|
||||||
|
CGImageRelease(cgImage);
|
||||||
|
}
|
||||||
|
return nsImage;
|
||||||
|
}
|
||||||
|
|
||||||
|
void qt_mac_set_app_icon(const QIcon &icon)
|
||||||
|
{
|
||||||
|
NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init];
|
||||||
|
NSImage *image = qt_mac_create_nsimage(icon);
|
||||||
|
[NSApp setApplicationIconImage:image];
|
||||||
|
[image release];
|
||||||
|
[pool release];
|
||||||
|
}
|
||||||
|
|
30
VMProtect/application.h
Normal file
@ -0,0 +1,30 @@
|
|||||||
|
#ifndef APPLICATION_H
|
||||||
|
#define APPLICATION_H
|
||||||
|
|
||||||
|
class Application : public QApplication
|
||||||
|
{
|
||||||
|
Q_OBJECT
|
||||||
|
public:
|
||||||
|
Application(int &argc, char **argv);
|
||||||
|
bool isHelpMode() { return help_filename_.length() > 0; }
|
||||||
|
const QString &helpFileName() const { return help_filename_; }
|
||||||
|
static double stylesheetScaleFactor() { return stylesheetScaleFactor_; }
|
||||||
|
static double devicePixelRatio() { return devicePixelRatio_; }
|
||||||
|
|
||||||
|
~Application();
|
||||||
|
|
||||||
|
signals:
|
||||||
|
void fileOpenEvent(const QString &);
|
||||||
|
|
||||||
|
protected:
|
||||||
|
/*virtual*/ bool event(QEvent *event);
|
||||||
|
|
||||||
|
void installStylesheet();
|
||||||
|
QByteArray transformStylesheet(const QByteArray &qssData);
|
||||||
|
void initScalingConstants();
|
||||||
|
static double stylesheetScaleFactor_, devicePixelRatio_;
|
||||||
|
|
||||||
|
QString help_filename_;
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif
|
132
VMProtect/application.qrc
Normal file
@ -0,0 +1,132 @@
|
|||||||
|
<!DOCTYPE RCC><RCC version="1.0">
|
||||||
|
<qresource>
|
||||||
|
<file>images/star.png</file>
|
||||||
|
<file>images/star_gray.png</file>
|
||||||
|
<file>images/tool.png</file>
|
||||||
|
<file>images/key.png</file>
|
||||||
|
<file>images/key_gray.png</file>
|
||||||
|
<file>images/bullet_key.png</file>
|
||||||
|
<file>images/bullet_import.png</file>
|
||||||
|
<file>images/box.png</file>
|
||||||
|
<file>images/folder.png</file>
|
||||||
|
<file>images/folder_close.png</file>
|
||||||
|
<file>images/item.png</file>
|
||||||
|
<file>images/item_m.png</file>
|
||||||
|
<file>images/item_v.png</file>
|
||||||
|
<file>images/item_u.png</file>
|
||||||
|
<file>images/item_file.png</file>
|
||||||
|
<file>images/item_key.png</file>
|
||||||
|
<file>images/item_import.png</file>
|
||||||
|
<file>images/item_export.png</file>
|
||||||
|
<file>images/item_resource.png</file>
|
||||||
|
<file>images/item_load_command.png</file>
|
||||||
|
<file>images/item_code.png</file>
|
||||||
|
<file>images/item_property.png</file>
|
||||||
|
<file>images/gear.png</file>
|
||||||
|
<file>images/import.png</file>
|
||||||
|
<file>images/export.png</file>
|
||||||
|
<file>images/code.png</file>
|
||||||
|
<file>images/dump.png</file>
|
||||||
|
<file>images/lightning.png</file>
|
||||||
|
<file>images/database.png</file>
|
||||||
|
<file>images/cancel.png</file>
|
||||||
|
<file>images/cancel_hover.png</file>
|
||||||
|
<file>images/cancel_gray.png</file>
|
||||||
|
<file>images/script.png</file>
|
||||||
|
<file>images/processor.png</file>
|
||||||
|
<file>images/cut.png</file>
|
||||||
|
<file>images/cut_hover.png</file>
|
||||||
|
<file>images/cut_disabled.png</file>
|
||||||
|
<file>images/copy.png</file>
|
||||||
|
<file>images/copy_hover.png</file>
|
||||||
|
<file>images/copy_disabled.png</file>
|
||||||
|
<file>images/paste.png</file>
|
||||||
|
<file>images/paste_hover.png</file>
|
||||||
|
<file>images/paste_disabled.png</file>
|
||||||
|
<file>images/add.png</file>
|
||||||
|
<file>images/add_hover.png</file>
|
||||||
|
<file>images/add_disabled.png</file>
|
||||||
|
<file>images/add_gray.png</file>
|
||||||
|
<file>images/delete.png</file>
|
||||||
|
<file>images/open.png</file>
|
||||||
|
<file>images/open_hover.png</file>
|
||||||
|
<file>images/open_disabled.png</file>
|
||||||
|
<file>images/disk.png</file>
|
||||||
|
<file>images/disk_hover.png</file>
|
||||||
|
<file>images/disk_disabled.png</file>
|
||||||
|
<file>images/information.png</file>
|
||||||
|
<file>images/warning.png</file>
|
||||||
|
<file>images/error.png</file>
|
||||||
|
<file>images/bullet_warning.png</file>
|
||||||
|
<file>images/compile.png</file>
|
||||||
|
<file>images/compile_hover.png</file>
|
||||||
|
<file>images/compile_disabled.png</file>
|
||||||
|
<file>images/execute.png</file>
|
||||||
|
<file>images/execute_hover.png</file>
|
||||||
|
<file>images/execute_disabled.png</file>
|
||||||
|
<file>images/link.png</file>
|
||||||
|
<file>images/disabled.png</file>
|
||||||
|
<file>images/reference.png</file>
|
||||||
|
<file>images/bullet_delete.png</file>
|
||||||
|
<file>images/boot_open.png</file>
|
||||||
|
<file>images/boot_help.png</file>
|
||||||
|
<file>images/boot_examples.png</file>
|
||||||
|
<file>images/branch_open.png</file>
|
||||||
|
<file>images/branch_closed.png</file>
|
||||||
|
<file>images/scroll_up.png</file>
|
||||||
|
<file>images/scroll_down.png</file>
|
||||||
|
<file>images/scroll_left.png</file>
|
||||||
|
<file>images/scroll_right.png</file>
|
||||||
|
<file>images/scroll_up_hover.png</file>
|
||||||
|
<file>images/scroll_down_hover.png</file>
|
||||||
|
<file>images/scroll_left_hover.png</file>
|
||||||
|
<file>images/scroll_right_hover.png</file>
|
||||||
|
<file>images/project.png</file>
|
||||||
|
<file>images/project_checked.png</file>
|
||||||
|
<file>images/project_hover.png</file>
|
||||||
|
<file>images/functions.png</file>
|
||||||
|
<file>images/functions_checked.png</file>
|
||||||
|
<file>images/functions_hover.png</file>
|
||||||
|
<file>images/details.png</file>
|
||||||
|
<file>images/details_checked.png</file>
|
||||||
|
<file>images/details_hover.png</file>
|
||||||
|
<file>images/logo.png</file>
|
||||||
|
<file>images/up_arrow.png</file>
|
||||||
|
<file>images/up_arrow_disabled.png</file>
|
||||||
|
<file>images/down_arrow.png</file>
|
||||||
|
<file>images/down_arrow_disabled.png</file>
|
||||||
|
<file>images/file_open.png</file>
|
||||||
|
<file>images/file_open_hover.png</file>
|
||||||
|
<file>images/up_down.png</file>
|
||||||
|
<file>images/up_down_disabled.png</file>
|
||||||
|
<file>images/browse.png</file>
|
||||||
|
<file>images/search.png</file>
|
||||||
|
<file>images/search_gray.png</file>
|
||||||
|
<file>images/checkbox.png</file>
|
||||||
|
<file>images/checkbox_checked.png</file>
|
||||||
|
<file>images/radiobutton.png</file>
|
||||||
|
<file>images/radiobutton_checked.png</file>
|
||||||
|
<file>images/menu_arrow.png</file>
|
||||||
|
<file>images/menu_arrow_hover.png</file>
|
||||||
|
<file>images/menu_arrow_disabled.png</file>
|
||||||
|
<file>images/goto.png</file>
|
||||||
|
<file>images/goto_hover.png</file>
|
||||||
|
<file>images/goto_disabled.png</file>
|
||||||
|
<file>images/back.png</file>
|
||||||
|
<file>images/back_hover.png</file>
|
||||||
|
<file>images/back_disabled.png</file>
|
||||||
|
<file>images/forward.png</file>
|
||||||
|
<file>images/forward_hover.png</file>
|
||||||
|
<file>images/forward_disabled.png</file>
|
||||||
|
<file>images/check_off.png</file>
|
||||||
|
<file>images/check_on.png</file>
|
||||||
|
<file>images/check_off_hover.png</file>
|
||||||
|
<file>images/check_on_hover.png</file>
|
||||||
|
<file>images/next.png</file>
|
||||||
|
<file>images/previous.png</file>
|
||||||
|
<file>images/help_gray.png</file>
|
||||||
|
<file>images/help_icon.png</file>
|
||||||
|
<file>images/calc.png</file>
|
||||||
|
<file>styles.qss</file>
|
||||||
|
</qresource>
|
||||||
|
</RCC>
|
0
VMProtect/export_key-pair.h
Normal file
168
VMProtect/export_key_pair_dialog.cc
Normal file
@ -0,0 +1,168 @@
|
|||||||
|
#ifdef ULTIMATE
|
||||||
|
#include "../core/objects.h"
|
||||||
|
#include "../core/core.h"
|
||||||
|
#include "../core/lang.h"
|
||||||
|
#include "export_key_pair_dialog.h"
|
||||||
|
#include "widgets.h"
|
||||||
|
#include "moc/moc_export_key_pair_dialog.cc"
|
||||||
|
#include "help_browser.h"
|
||||||
|
|
||||||
|
/**
|
||||||
|
* ExportKeyPairDialog
|
||||||
|
*/
|
||||||
|
|
||||||
|
ExportKeyPairDialog::ExportKeyPairDialog(QWidget *parent, LicensingManager *manager)
|
||||||
|
: QDialog(parent, Qt::WindowSystemMenuHint | Qt::WindowTitleHint)
|
||||||
|
{
|
||||||
|
bits_ = manager->bits();
|
||||||
|
private_exp_ = manager->private_exp();
|
||||||
|
public_exp_ = manager->public_exp();
|
||||||
|
modulus_ = manager->modulus();
|
||||||
|
uint64_t product_code = manager->product_code();
|
||||||
|
product_code_.insert(product_code_.end(), reinterpret_cast<uint8_t *>(&product_code), reinterpret_cast<uint8_t *>(&product_code) + sizeof(product_code));
|
||||||
|
|
||||||
|
setWindowTitle(QString::fromUtf8(language[lsExportKeyPair].c_str()));
|
||||||
|
|
||||||
|
QLabel *labelFormat = new QLabel(this);
|
||||||
|
labelFormat->setObjectName("header");
|
||||||
|
labelFormat->setText(QString::fromUtf8(language[lsKeyPairExportTarget].c_str()));
|
||||||
|
|
||||||
|
QComboBox *format = new QComboBox(this);
|
||||||
|
format->addItems(QStringList() << QString::fromUtf8(language[lsParametersForMSVC].c_str())
|
||||||
|
<< QString::fromUtf8(language[lsParametersForDelphi].c_str())
|
||||||
|
<< QString::fromUtf8(language[lsParametersForNET].c_str())
|
||||||
|
<< QString::fromUtf8(language[lsParametersForPHP].c_str()));
|
||||||
|
format->setCurrentIndex(0);
|
||||||
|
connect(format, SIGNAL(currentIndexChanged(int)), this, SLOT(formatChanged(int)));
|
||||||
|
|
||||||
|
QLabel *labelResults = new QLabel(this);
|
||||||
|
labelResults->setObjectName("header");
|
||||||
|
labelResults->setText(QString::fromUtf8(language[lsKeyPairExportResult].c_str()));
|
||||||
|
|
||||||
|
edit_ = new QPlainTextEdit(this);
|
||||||
|
QFont font = edit_->font();
|
||||||
|
font.setFamily(MONOSPACE_FONT_FAMILY);
|
||||||
|
edit_->setFont(font);
|
||||||
|
|
||||||
|
QToolButton *helpButton = new QToolButton(this);
|
||||||
|
helpButton->setShortcut(HelpContentsKeySequence());
|
||||||
|
helpButton->setIconSize(QSize(20, 20));
|
||||||
|
helpButton->setIcon(QIcon(":/images/help_gray.png"));
|
||||||
|
helpButton->setToolTip(QString::fromUtf8(language[lsHelp].c_str()));
|
||||||
|
connect(helpButton, SIGNAL(clicked(bool)), this, SLOT(helpClicked()));
|
||||||
|
|
||||||
|
QPushButton *closeButton = new PushButton(QString::fromUtf8(language[lsClose].c_str()));
|
||||||
|
connect(closeButton, SIGNAL(clicked()), this, SLOT(reject()));
|
||||||
|
|
||||||
|
QPushButton *copyButton = new PushButton(QString::fromUtf8(language[lsCopy].c_str()));
|
||||||
|
connect(copyButton, SIGNAL(clicked()), this, SLOT(copyClicked()));
|
||||||
|
|
||||||
|
QHBoxLayout *buttonLayout = new QHBoxLayout();
|
||||||
|
buttonLayout->addWidget(helpButton);
|
||||||
|
buttonLayout->addStretch();
|
||||||
|
#ifdef __APPLE__
|
||||||
|
buttonLayout->addWidget(closeButton);
|
||||||
|
buttonLayout->addWidget(copyButton);
|
||||||
|
#else
|
||||||
|
buttonLayout->addWidget(copyButton);
|
||||||
|
buttonLayout->addWidget(closeButton);
|
||||||
|
#endif
|
||||||
|
|
||||||
|
QVBoxLayout *layout = new QVBoxLayout();
|
||||||
|
layout->setContentsMargins(10, 10, 10, 10);
|
||||||
|
layout->setSpacing(10);
|
||||||
|
layout->addWidget(labelFormat);
|
||||||
|
layout->addWidget(format);
|
||||||
|
layout->addWidget(labelResults);
|
||||||
|
layout->addWidget(edit_);
|
||||||
|
layout->addLayout(buttonLayout);
|
||||||
|
setLayout(layout);
|
||||||
|
|
||||||
|
resize(610, 300);
|
||||||
|
|
||||||
|
formatChanged(format->currentIndex());
|
||||||
|
}
|
||||||
|
|
||||||
|
QString VectorToString(const std::vector<uint8_t> &value)
|
||||||
|
{
|
||||||
|
QString res;
|
||||||
|
for (size_t i = 0; i < value.size(); i++) {
|
||||||
|
if (i > 0)
|
||||||
|
res.append(',').append((i & 0xf) ? ' ' : '\n');
|
||||||
|
res.append(QString("%1").arg(value[i], 3, 10, QChar(' ')));
|
||||||
|
}
|
||||||
|
|
||||||
|
return res;
|
||||||
|
}
|
||||||
|
|
||||||
|
QString _VectorToBase64(const std::vector<uint8_t> &value)
|
||||||
|
{
|
||||||
|
QByteArray res = QByteArray(reinterpret_cast<const char *>(&value[0]), (int)value.size());
|
||||||
|
return res.toBase64();
|
||||||
|
}
|
||||||
|
|
||||||
|
QString StringToBase64(const QString &value)
|
||||||
|
{
|
||||||
|
QByteArray res;
|
||||||
|
res.append(value);
|
||||||
|
return res.toBase64();
|
||||||
|
}
|
||||||
|
|
||||||
|
void ExportKeyPairDialog::formatChanged(int format)
|
||||||
|
{
|
||||||
|
QStringList lines;
|
||||||
|
switch (format) {
|
||||||
|
case 0:
|
||||||
|
lines.append("VMProtectAlgorithms g_Algorithm = ALGORITHM_RSA;");
|
||||||
|
lines.append(QString("size_t g_nBits = %1;").arg(bits_));
|
||||||
|
lines.append(QString("byte g_vPrivate[%1] = {").arg(private_exp_.size()));
|
||||||
|
lines.append(VectorToString(private_exp_) + "};");
|
||||||
|
lines.append("");
|
||||||
|
lines.append(QString("byte g_vModulus[%1] = {").arg(modulus_.size()));
|
||||||
|
lines.append(VectorToString(modulus_) + "};");
|
||||||
|
lines.append("");
|
||||||
|
lines.append(QString("byte g_vProductCode[%1] = {%2};").arg(product_code_.size()).arg(VectorToString(product_code_)));
|
||||||
|
break;
|
||||||
|
case 1:
|
||||||
|
lines.append("g_Algorithm: Longword = ALGORITHM_RSA;");
|
||||||
|
lines.append(QString("g_nBits: Longword = %1;").arg(bits_));
|
||||||
|
lines.append(QString("g_vPrivate: array [0..%1] of Byte = (").arg(private_exp_.size() - 1));
|
||||||
|
lines.append(VectorToString(private_exp_) + ");");
|
||||||
|
lines.append("");
|
||||||
|
lines.append(QString("g_vModulus: array [0..%1] of Byte = (").arg(modulus_.size() - 1));
|
||||||
|
lines.append(VectorToString(modulus_) + ");");
|
||||||
|
lines.append("");
|
||||||
|
lines.append(QString("g_vProductCode: array [0..%1] of Byte = (%2);").arg(product_code_.size() - 1).arg(VectorToString(product_code_)));
|
||||||
|
break;
|
||||||
|
case 2:
|
||||||
|
{
|
||||||
|
QString str = StringToBase64(QString("<vmp-lm-product algorithm=\"RSA\" bits=\"%1\" exp=\"%2\" mod=\"%3\" product=\"%4\"/>").arg(bits_).arg(_VectorToBase64(private_exp_)).arg(_VectorToBase64(modulus_)).arg(_VectorToBase64(product_code_)));
|
||||||
|
while (!str.isEmpty()) {
|
||||||
|
lines.append(str.left(76));
|
||||||
|
str.remove(0, 76);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case 3:
|
||||||
|
lines.append("$exported_algorithm = \"RSA\";");
|
||||||
|
lines.append(QString("$exported_bits = %1;").arg(bits_));
|
||||||
|
lines.append(QString("$exported_private = \"%1\";").arg(_VectorToBase64(private_exp_)));
|
||||||
|
lines.append(QString("$exported_modulus = \"%1\";").arg(_VectorToBase64(modulus_)));
|
||||||
|
lines.append(QString("$exported_product_code = \"%1\";").arg(_VectorToBase64(product_code_)));
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
edit_->setPlainText(lines.join("\n"));
|
||||||
|
}
|
||||||
|
|
||||||
|
void ExportKeyPairDialog::copyClicked()
|
||||||
|
{
|
||||||
|
QClipboard *clipboard = QApplication::clipboard();
|
||||||
|
clipboard->setText(edit_->toPlainText());
|
||||||
|
}
|
||||||
|
|
||||||
|
void ExportKeyPairDialog::helpClicked()
|
||||||
|
{
|
||||||
|
HelpBrowser::showTopic("project::licenses");
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif
|
23
VMProtect/export_key_pair_dialog.h
Normal file
@ -0,0 +1,23 @@
|
|||||||
|
#ifndef EXPORT_KEY_PAIR_DIALOG_H
|
||||||
|
#define EXPORT_KEY_PAIR_DIALOG_H
|
||||||
|
|
||||||
|
class ExportKeyPairDialog : public QDialog
|
||||||
|
{
|
||||||
|
Q_OBJECT
|
||||||
|
public:
|
||||||
|
ExportKeyPairDialog(QWidget *parent, LicensingManager *manager);
|
||||||
|
private slots:
|
||||||
|
void formatChanged(int format);
|
||||||
|
void copyClicked();
|
||||||
|
void helpClicked();
|
||||||
|
private:
|
||||||
|
size_t bits_;
|
||||||
|
std::vector<uint8_t> public_exp_;
|
||||||
|
std::vector<uint8_t> private_exp_;
|
||||||
|
std::vector<uint8_t> modulus_;
|
||||||
|
std::vector<uint8_t> product_code_;
|
||||||
|
|
||||||
|
QPlainTextEdit *edit_;
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif
|
19
VMProtect/folder_dialog.h
Normal file
@ -0,0 +1,19 @@
|
|||||||
|
#ifndef FOLDER_DIALOG_H
|
||||||
|
#define FOLDER_DIALOG_H
|
||||||
|
|
||||||
|
#include <QtGui/QDialog>
|
||||||
|
#include <QtGui/QtGui>
|
||||||
|
|
||||||
|
class FolderDialog : public QDialog
|
||||||
|
{
|
||||||
|
Q_OBJECT
|
||||||
|
|
||||||
|
public:
|
||||||
|
FolderDialog(QWidget *parent = NULL);
|
||||||
|
QString nameText() const { return nameEdit->text(); }
|
||||||
|
void setNameText(const QString &text) { nameEdit->setText(text); }
|
||||||
|
private:
|
||||||
|
QLineEdit *nameEdit;
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif
|
265
VMProtect/function_dialog.cc
Normal file
@ -0,0 +1,265 @@
|
|||||||
|
#include "../core/objects.h"
|
||||||
|
#include "../core/core.h"
|
||||||
|
#include "../core/lang.h"
|
||||||
|
#include "../core/files.h"
|
||||||
|
#include "../core/processors.h"
|
||||||
|
|
||||||
|
#include "widgets.h"
|
||||||
|
#include "models.h"
|
||||||
|
#include "property_editor.h"
|
||||||
|
#include "function_dialog.h"
|
||||||
|
#include "message_dialog.h"
|
||||||
|
#include "help_browser.h"
|
||||||
|
#include "moc/moc_function_dialog.cc"
|
||||||
|
#include "application.h"
|
||||||
|
|
||||||
|
/**
|
||||||
|
* FunctionDialog
|
||||||
|
*/
|
||||||
|
|
||||||
|
FunctionDialog::FunctionDialog(IFile *file, IArchitecture *file_arch, ShowMode mode, QWidget *parent)
|
||||||
|
: QDialog(parent, Qt::WindowSystemMenuHint | Qt::WindowTitleHint | Qt::CustomizeWindowHint | Qt::WindowCloseButtonHint), file_(file), mode_(mode), defaultArch_(NULL)
|
||||||
|
{
|
||||||
|
setWindowTitle(QString::fromUtf8(language[mode_ == smAddFunction ? lsAddFunction : lsGoTo].c_str()));
|
||||||
|
|
||||||
|
if (file_arch) {
|
||||||
|
functionListModel_.reset(new MapFunctionListModel(*file_arch, (mode_ == smAddFunction), this));
|
||||||
|
defaultArch_ = file_arch;
|
||||||
|
} else {
|
||||||
|
functionBundleListModel_.reset(new MapFunctionBundleListModel(*file, (mode_ == smAddFunction), this));
|
||||||
|
if (!file_->map_function_list()->show_arch_name()) {
|
||||||
|
for (size_t i = 0; i < file_->count(); i++) {
|
||||||
|
IArchitecture *arch = file_->item(i);
|
||||||
|
if (!arch->visible())
|
||||||
|
continue;
|
||||||
|
|
||||||
|
defaultArch_ = arch;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
QLabel *addressLabel = new QLabel(QString::fromUtf8(language[lsAddress].c_str()), this);
|
||||||
|
addressEdit_ = new LineEdit(this);
|
||||||
|
tabBar_ = new TabWidget(this);
|
||||||
|
tabBar_->setIconSize(QSize(18, 18));
|
||||||
|
|
||||||
|
QFrame *panel;
|
||||||
|
QLayout *panelLayout;
|
||||||
|
|
||||||
|
functionsTree_ = new TreeView(this);
|
||||||
|
functionsTree_->setObjectName("grid");
|
||||||
|
functionsTree_->setIconSize(QSize(18, 18));
|
||||||
|
functionsTree_->setRootIsDecorated(false);
|
||||||
|
functionsTree_->setUniformRowHeights(true);
|
||||||
|
if (functionBundleListModel_.get())
|
||||||
|
functionsTree_->setModel(functionBundleListModel_.get());
|
||||||
|
else
|
||||||
|
functionsTree_->setModel(functionListModel_.get());
|
||||||
|
if (mode_ == smAddFunction)
|
||||||
|
functionsTree_->setSelectionMode(QTreeView::ExtendedSelection);
|
||||||
|
functionsTree_->setSelectionBehavior(QTreeView::SelectRows);
|
||||||
|
functionsTree_->setEditTriggers(QAbstractItemView::NoEditTriggers);
|
||||||
|
functionsTree_->header()->resizeSection(0, 240 * Application::stylesheetScaleFactor());
|
||||||
|
functionsTree_->header()->setSectionsMovable(false);
|
||||||
|
functionsTree_->header()->setSectionsClickable(true);
|
||||||
|
connect(functionsTree_->selectionModel(), SIGNAL(selectionChanged(QItemSelection, QItemSelection)),
|
||||||
|
this, SLOT(functionsTreeSelectionChanged(QItemSelection, QItemSelection)));
|
||||||
|
connect(functionsTree_, SIGNAL(doubleClicked(QModelIndex)), this, SLOT(okButtonClicked()));
|
||||||
|
connect(functionsTree_->header(), SIGNAL(sectionClicked(int)), this, SLOT(sectionClicked(int)));
|
||||||
|
|
||||||
|
functionsFilter_ = new SearchLineEdit(this);
|
||||||
|
functionsFilter_->setPlaceholderText(QString::fromUtf8(language[lsSearch].c_str()));
|
||||||
|
connect(functionsFilter_, SIGNAL(textChanged(const QString &)), this, SLOT(functionsFilterChanged()));
|
||||||
|
connect(functionsFilter_, SIGNAL(returnPressed()), this, SLOT(functionsFilterChanged()));
|
||||||
|
|
||||||
|
panel = new QFrame(this);
|
||||||
|
panelLayout = new QVBoxLayout();
|
||||||
|
panelLayout->setContentsMargins(0, 10, 0, 0);
|
||||||
|
panelLayout->setSpacing(10);
|
||||||
|
panelLayout->addWidget(functionsFilter_);
|
||||||
|
panelLayout->addWidget(functionsTree_);
|
||||||
|
panel->setLayout(panelLayout);
|
||||||
|
tabBar_->addTab(panel, QIcon(":/images/star_gray.png"), QString::fromUtf8(language[lsFunctions].c_str()));
|
||||||
|
|
||||||
|
if (mode_ == smAddFunction) {
|
||||||
|
PropertyManager *propertyManager = new PropertyManager(this);
|
||||||
|
GroupProperty *protection = propertyManager->addGroupProperty(NULL, QString::fromUtf8(language[lsProtection].c_str()));
|
||||||
|
compilationType_ = propertyManager->addEnumProperty(protection, QString::fromUtf8(language[lsCompilationType].c_str()),
|
||||||
|
QStringList() << QString::fromUtf8(language[lsVirtualization].c_str())
|
||||||
|
<< QString::fromUtf8(language[lsMutation].c_str())
|
||||||
|
<< QString("%1 (%2 + %3)").arg(QString::fromUtf8(language[lsUltra].c_str())).arg(QString::fromUtf8(language[lsMutation].c_str())).arg(QString::fromUtf8(language[lsVirtualization].c_str())), 0);
|
||||||
|
lockToKey_ = propertyManager->addBoolProperty(protection, QString::fromUtf8(language[lsLockToSerialNumber].c_str()), false);
|
||||||
|
|
||||||
|
TreePropertyEditor *optionsTree = new TreePropertyEditor(this);
|
||||||
|
optionsTree->setFrameShape(QFrame::Box);
|
||||||
|
optionsTree->setModel(propertyManager);
|
||||||
|
optionsTree->expandToDepth(0);
|
||||||
|
optionsTree->header()->resizeSection(0, 240 * Application::stylesheetScaleFactor());
|
||||||
|
optionsTree->header()->setSectionsMovable(false);
|
||||||
|
|
||||||
|
panel = new QFrame(this);
|
||||||
|
panelLayout = new QVBoxLayout();
|
||||||
|
panelLayout->setContentsMargins(0, 10, 0, 0);
|
||||||
|
panelLayout->addWidget(optionsTree);
|
||||||
|
panel->setLayout(panelLayout);
|
||||||
|
tabBar_->addTab(panel, QIcon(":/images/gear.png"), QString::fromUtf8(language[lsOptions].c_str()));
|
||||||
|
}
|
||||||
|
|
||||||
|
QToolButton *helpButton = new QToolButton(this);
|
||||||
|
helpButton->setShortcut(HelpContentsKeySequence());
|
||||||
|
helpButton->setIconSize(QSize(20, 20));
|
||||||
|
helpButton->setIcon(QIcon(":/images/help_gray.png"));
|
||||||
|
helpButton->setToolTip(QString::fromUtf8(language[lsHelp].c_str()));
|
||||||
|
connect(helpButton, SIGNAL(clicked(bool)), this, SLOT(helpClicked()));
|
||||||
|
|
||||||
|
QPushButton *okButton = new PushButton(windowTitle(), this);
|
||||||
|
connect(okButton, SIGNAL(clicked()), this, SLOT(okButtonClicked()));
|
||||||
|
|
||||||
|
QPushButton *cancelButton = new PushButton(QString::fromUtf8(language[lsCancel].c_str()), this);
|
||||||
|
connect(cancelButton, SIGNAL(clicked()), this, SLOT(reject()));
|
||||||
|
|
||||||
|
QHBoxLayout *buttonLayout = new QHBoxLayout();
|
||||||
|
buttonLayout->setContentsMargins(0, 0, 0, 0);
|
||||||
|
buttonLayout->setSpacing(10);
|
||||||
|
buttonLayout->addWidget(helpButton);
|
||||||
|
buttonLayout->addStretch();
|
||||||
|
#ifdef __APPLE__
|
||||||
|
buttonLayout->addWidget(cancelButton);
|
||||||
|
buttonLayout->addWidget(okButton);
|
||||||
|
#else
|
||||||
|
buttonLayout->addWidget(okButton);
|
||||||
|
buttonLayout->addWidget(cancelButton);
|
||||||
|
#endif
|
||||||
|
|
||||||
|
QGridLayout *layout = new QGridLayout();
|
||||||
|
layout->setContentsMargins(10, 10, 10, 10);
|
||||||
|
layout->setSpacing(10);
|
||||||
|
layout->addWidget(addressLabel, 0, 0);
|
||||||
|
layout->addWidget(addressEdit_, 0, 1);
|
||||||
|
layout->addWidget(tabBar_, 1, 0, 1, 2);
|
||||||
|
layout->addLayout(buttonLayout, 2, 0, 1, 2);
|
||||||
|
setLayout(layout);
|
||||||
|
|
||||||
|
setMinimumSize(480 * Application::stylesheetScaleFactor(), 300 * Application::stylesheetScaleFactor());
|
||||||
|
}
|
||||||
|
|
||||||
|
bool FunctionDialog::checkAddress(const AddressInfo &info)
|
||||||
|
{
|
||||||
|
if (!info.arch)
|
||||||
|
return false;
|
||||||
|
|
||||||
|
if (mode_ == smAddFunction) {
|
||||||
|
if (info.arch->segment_list()->GetMemoryTypeByAddress(info.address) & mtExecutable) {
|
||||||
|
return true;
|
||||||
|
} else {
|
||||||
|
MapFunction *func = info.arch->map_function_list()->GetFunctionByAddress(info.address);
|
||||||
|
if (func && func->type() == otString)
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
if (info.arch->segment_list()->GetSectionByAddress(info.address))
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
void FunctionDialog::okButtonClicked()
|
||||||
|
{
|
||||||
|
addresses_.clear();
|
||||||
|
|
||||||
|
bool show_arch_name = file_->map_function_list()->show_arch_name();
|
||||||
|
|
||||||
|
QStringList address_list = addressEdit_->text().split(',');
|
||||||
|
if (address_list.isEmpty())
|
||||||
|
address_list.append("0");
|
||||||
|
|
||||||
|
QString address_str;
|
||||||
|
AddressInfo info;
|
||||||
|
info.arch = NULL;
|
||||||
|
int p = 0;
|
||||||
|
for (int i = 0; i < address_list.size(); i++) {
|
||||||
|
address_str = address_list[i].trimmed();
|
||||||
|
info.arch = defaultArch_;
|
||||||
|
if (show_arch_name) {
|
||||||
|
int dot_pos = address_str.indexOf('.');
|
||||||
|
if (dot_pos > -1) {
|
||||||
|
info.arch = file_->GetArchitectureByName(address_str.left(dot_pos).toUtf8().constData());
|
||||||
|
address_str.remove(0, dot_pos + 1);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
bool is_valid;
|
||||||
|
info.address = address_str.toULongLong(&is_valid, 16);
|
||||||
|
|
||||||
|
if (!is_valid || !checkAddress(info)) {
|
||||||
|
MessageDialog::critical(this, "Invalid address", QMessageBox::Ok);
|
||||||
|
addressEdit_->setFocus();
|
||||||
|
addressEdit_->setCursorPosition(p);
|
||||||
|
addressEdit_->cursorForward(true, address_list[i].size());
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
addresses_.append(info);
|
||||||
|
p += address_list[i].size() + 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
accept();
|
||||||
|
}
|
||||||
|
|
||||||
|
void FunctionDialog::functionsTreeSelectionChanged(const QItemSelection & /*selected*/, const QItemSelection & /*deselected*/)
|
||||||
|
{
|
||||||
|
QModelIndexList list;
|
||||||
|
|
||||||
|
list = functionsTree_->selectionModel()->selectedIndexes();
|
||||||
|
|
||||||
|
QString address;
|
||||||
|
for (int i = 0; i < list.size(); i++) {
|
||||||
|
QModelIndex index = list.at(i);
|
||||||
|
if (index.column() != 0)
|
||||||
|
continue;
|
||||||
|
|
||||||
|
if (!address.isEmpty())
|
||||||
|
address.append(", ");
|
||||||
|
if (functionBundleListModel_.get()) {
|
||||||
|
MapFunctionBundle *func = static_cast<MapFunctionBundle *>(index.internalPointer());
|
||||||
|
address.append(QString::fromLatin1(func->display_address().c_str()));
|
||||||
|
} else {
|
||||||
|
MapFunction *func = static_cast<MapFunction *>(index.internalPointer());
|
||||||
|
address.append(QString::fromLatin1(func->display_address("").c_str()));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
addressEdit_->setText(address);
|
||||||
|
}
|
||||||
|
|
||||||
|
CompilationType FunctionDialog::compilationType() const
|
||||||
|
{
|
||||||
|
return static_cast<CompilationType>(compilationType_->value());
|
||||||
|
}
|
||||||
|
|
||||||
|
uint32_t FunctionDialog::compilationOptions() const
|
||||||
|
{
|
||||||
|
uint32_t res = 0;
|
||||||
|
if (lockToKey_->value())
|
||||||
|
res |= coLockToKey;
|
||||||
|
return res;
|
||||||
|
}
|
||||||
|
|
||||||
|
void FunctionDialog::functionsFilterChanged()
|
||||||
|
{
|
||||||
|
if (functionBundleListModel_.get())
|
||||||
|
functionBundleListModel_->search(functionsFilter_->text());
|
||||||
|
else
|
||||||
|
functionListModel_->search(functionsFilter_->text());
|
||||||
|
}
|
||||||
|
|
||||||
|
void FunctionDialog::helpClicked()
|
||||||
|
{
|
||||||
|
HelpBrowser::showTopic(tabBar_->currentIndex() == 0 ? "functions::search" : "functions::setup");
|
||||||
|
}
|
||||||
|
|
||||||
|
void FunctionDialog::sectionClicked(int index)
|
||||||
|
{
|
||||||
|
auto mdl = functionsTree_->model();
|
||||||
|
assert(mdl);
|
||||||
|
if (mdl)
|
||||||
|
mdl->sort(index);
|
||||||
|
}
|
45
VMProtect/function_dialog.h
Normal file
@ -0,0 +1,45 @@
|
|||||||
|
#ifndef FUNCTION_DIALOG_H
|
||||||
|
#define FUNCTION_DIALOG_H
|
||||||
|
|
||||||
|
struct AddressInfo {
|
||||||
|
uint64_t address;
|
||||||
|
IArchitecture *arch;
|
||||||
|
};
|
||||||
|
|
||||||
|
enum ShowMode {
|
||||||
|
smAddFunction,
|
||||||
|
smGotoAddress
|
||||||
|
};
|
||||||
|
|
||||||
|
class FunctionDialog : public QDialog
|
||||||
|
{
|
||||||
|
Q_OBJECT
|
||||||
|
public:
|
||||||
|
FunctionDialog(IFile *file, IArchitecture *arch, ShowMode mode, QWidget *parent = NULL);
|
||||||
|
QList<AddressInfo> addresses() const { return addresses_; }
|
||||||
|
CompilationType compilationType() const;
|
||||||
|
uint32_t compilationOptions() const;
|
||||||
|
private slots:
|
||||||
|
void okButtonClicked();
|
||||||
|
void functionsTreeSelectionChanged(const QItemSelection &selected, const QItemSelection &deselected);
|
||||||
|
void functionsFilterChanged();
|
||||||
|
void helpClicked();
|
||||||
|
void sectionClicked(int index);
|
||||||
|
private:
|
||||||
|
bool checkAddress(const AddressInfo &info);
|
||||||
|
|
||||||
|
QTabWidget *tabBar_;
|
||||||
|
IFile *file_;
|
||||||
|
ShowMode mode_;
|
||||||
|
QLineEdit *addressEdit_;
|
||||||
|
SearchLineEdit *functionsFilter_;
|
||||||
|
QTreeView *functionsTree_;
|
||||||
|
QList<AddressInfo> addresses_;
|
||||||
|
EnumProperty *compilationType_;
|
||||||
|
BoolProperty *lockToKey_;
|
||||||
|
std::auto_ptr<MapFunctionBundleListModel> functionBundleListModel_;
|
||||||
|
std::auto_ptr<MapFunctionListModel> functionListModel_;
|
||||||
|
IArchitecture *defaultArch_;
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif
|
689
VMProtect/help_browser.cc
Normal file
@ -0,0 +1,689 @@
|
|||||||
|
#include "help_browser.h"
|
||||||
|
#include "message_dialog.h"
|
||||||
|
#include "widgets.h"
|
||||||
|
#include "moc/moc_help_browser.cc"
|
||||||
|
#include "../core/objects.h"
|
||||||
|
#include "../core/lang.h"
|
||||||
|
#include "../core/inifile.h"
|
||||||
|
#include "remotecontrol.h"
|
||||||
|
|
||||||
|
/**
|
||||||
|
* HelpContentModel
|
||||||
|
*/
|
||||||
|
|
||||||
|
HelpContentModel::HelpContentModel(QHelpEngine *engine, QObject *parent)
|
||||||
|
: QIdentityProxyModel(parent)
|
||||||
|
{
|
||||||
|
setSourceModel(engine->contentModel());
|
||||||
|
}
|
||||||
|
|
||||||
|
QVariant HelpContentModel::data(const QModelIndex &index, int role) const
|
||||||
|
{
|
||||||
|
if (role == Qt::FontRole) {
|
||||||
|
if (!index.parent().isValid()) {
|
||||||
|
// top level
|
||||||
|
QFont font;
|
||||||
|
font.setBold(true);
|
||||||
|
return font;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return QIdentityProxyModel::data(index, role);
|
||||||
|
}
|
||||||
|
|
||||||
|
QVariant HelpContentModel::headerData(int section, Qt::Orientation orientation, int role) const
|
||||||
|
{
|
||||||
|
if (role == Qt::DisplayRole) {
|
||||||
|
if (section == 0)
|
||||||
|
return QString::fromUtf8(language[lsContents].c_str());
|
||||||
|
}
|
||||||
|
return QIdentityProxyModel::headerData(section, orientation, role);
|
||||||
|
}
|
||||||
|
|
||||||
|
QHelpContentItem *HelpContentModel::contentItemAt(const QModelIndex &index) const
|
||||||
|
{
|
||||||
|
QHelpContentModel *model = qobject_cast<QHelpContentModel*>(sourceModel());
|
||||||
|
if (model)
|
||||||
|
return model->contentItemAt(index);
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
QModelIndex HelpContentModel::indexOf(const QUrl &link)
|
||||||
|
{
|
||||||
|
if (link.scheme() != QLatin1String("qthelp"))
|
||||||
|
return QModelIndex();
|
||||||
|
|
||||||
|
QString fragment = link.fragment();
|
||||||
|
for (int i = 0; i < rowCount(); ++i) {
|
||||||
|
QHelpContentItem *item = contentItemAt(index(i, 0));
|
||||||
|
if (item && item->url().host() == link.host()) {
|
||||||
|
QString path = link.path();
|
||||||
|
//if (path.startsWith(QLatin1Char('/')))
|
||||||
|
// path = path.mid(1);
|
||||||
|
QModelIndex res = searchContentItem(index(i, 0), path);
|
||||||
|
if (res.isValid()) {
|
||||||
|
if (!fragment.isEmpty()) {
|
||||||
|
item = contentItemAt(res);
|
||||||
|
assert(item);
|
||||||
|
for (int j = 0; item && (j < item->childCount()); ++j) {
|
||||||
|
auto ch = item->child(j);
|
||||||
|
assert(ch);
|
||||||
|
if (ch && (ch->url().fragment() == fragment)) {
|
||||||
|
res = index(j, 0, res);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return res;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return QModelIndex();
|
||||||
|
}
|
||||||
|
|
||||||
|
QModelIndex HelpContentModel::searchContentItem(const QModelIndex &parent, const QString &path)
|
||||||
|
{
|
||||||
|
QHelpContentItem *parentItem = contentItemAt(parent);
|
||||||
|
if (!parentItem)
|
||||||
|
return QModelIndex();
|
||||||
|
|
||||||
|
QString cpath = parentItem->url().path();
|
||||||
|
if (cpath == path)
|
||||||
|
return parent;
|
||||||
|
|
||||||
|
for (int i = 0; i < parentItem->childCount(); ++i) {
|
||||||
|
QModelIndex res = searchContentItem(index(i, 0, parent), path);
|
||||||
|
if (res.isValid())
|
||||||
|
return res;
|
||||||
|
}
|
||||||
|
return QModelIndex();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* HelpResultItem
|
||||||
|
*/
|
||||||
|
|
||||||
|
HelpResultItem::HelpResultItem(const QString &title, const QString &url, const QString &toolTip)
|
||||||
|
: title_(title), url_(url), toolTip_(toolTip), parent_(NULL)
|
||||||
|
{
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
HelpResultItem::~HelpResultItem()
|
||||||
|
{
|
||||||
|
clear();
|
||||||
|
if (parent_)
|
||||||
|
parent_->removeChild(this);
|
||||||
|
}
|
||||||
|
|
||||||
|
void HelpResultItem::clear()
|
||||||
|
{
|
||||||
|
for (int i = 0; i < children_.size(); i++) {
|
||||||
|
HelpResultItem *item = children_[i];
|
||||||
|
item->parent_ = NULL;
|
||||||
|
delete item;
|
||||||
|
}
|
||||||
|
children_.clear();
|
||||||
|
}
|
||||||
|
|
||||||
|
void HelpResultItem::addChild(HelpResultItem *child)
|
||||||
|
{
|
||||||
|
insertChild(childCount(), child);
|
||||||
|
}
|
||||||
|
|
||||||
|
void HelpResultItem::insertChild(int index, HelpResultItem *child)
|
||||||
|
{
|
||||||
|
if (child->parent())
|
||||||
|
return;
|
||||||
|
|
||||||
|
child->parent_ = this;
|
||||||
|
children_.insert(index, child);
|
||||||
|
}
|
||||||
|
|
||||||
|
void HelpResultItem::removeChild(HelpResultItem *child)
|
||||||
|
{
|
||||||
|
if (children_.removeOne(child))
|
||||||
|
child->parent_ = NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* HelpResultModel
|
||||||
|
*/
|
||||||
|
|
||||||
|
HelpResultModel::HelpResultModel(QHelpEngine *engine, QObject *parent)
|
||||||
|
: QAbstractItemModel(parent), engine_(engine)
|
||||||
|
{
|
||||||
|
root_ = new HelpResultItem(QString(), QString(), QString());
|
||||||
|
|
||||||
|
connect(engine_->searchEngine(), SIGNAL(searchingFinished(int)), this, SLOT(searchingFinished()));
|
||||||
|
}
|
||||||
|
|
||||||
|
HelpResultModel::~HelpResultModel()
|
||||||
|
{
|
||||||
|
delete root_;
|
||||||
|
}
|
||||||
|
|
||||||
|
QModelIndex HelpResultModel::parent(const QModelIndex &index) const
|
||||||
|
{
|
||||||
|
if (!index.isValid())
|
||||||
|
return QModelIndex();
|
||||||
|
|
||||||
|
HelpResultItem *childItem = itemAt(index);
|
||||||
|
HelpResultItem *parentItem = childItem->parent();
|
||||||
|
if (parentItem == root_)
|
||||||
|
return QModelIndex();
|
||||||
|
|
||||||
|
return createIndex(parentItem->parent()->children().indexOf(parentItem), 0, parentItem);
|
||||||
|
}
|
||||||
|
|
||||||
|
int HelpResultModel::columnCount(const QModelIndex & /* parent */) const
|
||||||
|
{
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
QVariant HelpResultModel::headerData(int section, Qt::Orientation orientation, int role) const
|
||||||
|
{
|
||||||
|
if (role == Qt::DisplayRole) {
|
||||||
|
if (section == 0)
|
||||||
|
return QString::fromUtf8(language[lsSearchResult].c_str());
|
||||||
|
}
|
||||||
|
return QVariant();
|
||||||
|
}
|
||||||
|
|
||||||
|
int HelpResultModel::rowCount(const QModelIndex &parent) const
|
||||||
|
{
|
||||||
|
HelpResultItem *parentItem = itemAt(parent);
|
||||||
|
return parentItem->childCount();
|
||||||
|
}
|
||||||
|
|
||||||
|
QVariant HelpResultModel::data(const QModelIndex &index, int role) const
|
||||||
|
{
|
||||||
|
if (!index.isValid())
|
||||||
|
return QVariant();
|
||||||
|
|
||||||
|
HelpResultItem *item = itemAt(index);
|
||||||
|
switch (role) {
|
||||||
|
case Qt::DisplayRole:
|
||||||
|
return item->title();
|
||||||
|
case Qt::ToolTipRole:
|
||||||
|
return item->toolTip();
|
||||||
|
case Qt::FontRole:
|
||||||
|
if (!index.parent().isValid()) {
|
||||||
|
// top level
|
||||||
|
QFont font;
|
||||||
|
font.setBold(true);
|
||||||
|
return font;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
return QVariant();
|
||||||
|
}
|
||||||
|
|
||||||
|
QModelIndex HelpResultModel::index(int row, int column, const QModelIndex &parent) const
|
||||||
|
{
|
||||||
|
if (parent.isValid() && parent.column() != 0)
|
||||||
|
return QModelIndex();
|
||||||
|
|
||||||
|
HelpResultItem *parentItem = itemAt(parent);
|
||||||
|
HelpResultItem *childItem = parentItem->child(row);
|
||||||
|
if (!childItem)
|
||||||
|
return QModelIndex();
|
||||||
|
|
||||||
|
return createIndex(row, column, childItem);
|
||||||
|
}
|
||||||
|
|
||||||
|
HelpResultItem *HelpResultModel::itemAt(const QModelIndex &index) const
|
||||||
|
{
|
||||||
|
if (index.isValid())
|
||||||
|
return static_cast<HelpResultItem *>(index.internalPointer());
|
||||||
|
return root_;
|
||||||
|
}
|
||||||
|
|
||||||
|
void HelpResultModel::search(const QString &text)
|
||||||
|
{
|
||||||
|
QHelpSearchQuery q(QHelpSearchQuery::DEFAULT, QStringList(text));
|
||||||
|
QList<QHelpSearchQuery> ql;
|
||||||
|
ql.append(q);
|
||||||
|
engine_->searchEngine()->search(ql);
|
||||||
|
}
|
||||||
|
|
||||||
|
void HelpResultModel::searchingFinished()
|
||||||
|
{
|
||||||
|
beginResetModel();
|
||||||
|
|
||||||
|
root_->clear();
|
||||||
|
QList<QHelpSearchEngine::SearchHit> hits = engine_->searchEngine()->hits(0, engine_->searchEngine()->hitsCount());
|
||||||
|
foreach(const QHelpSearchEngine::SearchHit &hit, hits) {
|
||||||
|
QString toolTip;
|
||||||
|
QModelIndex index = engine_->contentWidget()->indexOf(hit.first);
|
||||||
|
while (index.isValid()) {
|
||||||
|
QHelpContentItem *item = engine_->contentModel()->contentItemAt(index);
|
||||||
|
if (item) {
|
||||||
|
if (!toolTip.isEmpty())
|
||||||
|
toolTip = " > " + toolTip;
|
||||||
|
toolTip = item->title() + toolTip;
|
||||||
|
}
|
||||||
|
index = index.parent();
|
||||||
|
}
|
||||||
|
root_->addChild(new HelpResultItem(hit.second, hit.first, toolTip));
|
||||||
|
}
|
||||||
|
|
||||||
|
endResetModel();
|
||||||
|
|
||||||
|
emit finished(root_->childCount());
|
||||||
|
}
|
||||||
|
|
||||||
|
class TextBrowser : public QTextBrowser
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
TextBrowser(QHelpEngine *helpEngine, QWidget *parent_ = 0): QTextBrowser(parent_), helpEngine_(helpEngine) {}
|
||||||
|
QVariant loadResource(int type, const QUrl &url)
|
||||||
|
{
|
||||||
|
const QString &scheme = url.scheme();
|
||||||
|
if(scheme == "qthelp")
|
||||||
|
return QVariant(helpEngine_->fileData(url));
|
||||||
|
else
|
||||||
|
return QTextBrowser::loadResource(type, url);
|
||||||
|
}
|
||||||
|
bool navigateToKeyword(const QString &keywordId)
|
||||||
|
{
|
||||||
|
auto links = helpEngine_->linksForIdentifier(keywordId);
|
||||||
|
if(links.count() > 0)
|
||||||
|
{
|
||||||
|
setSource(links.begin().value());
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
void setSource(const QUrl &src)
|
||||||
|
{
|
||||||
|
const QUrl &prevSrc = source();
|
||||||
|
if(src == prevSrc) return;
|
||||||
|
|
||||||
|
const QString &scheme = src.scheme();
|
||||||
|
if(scheme != "qthelp")
|
||||||
|
{
|
||||||
|
QDesktopServices::openUrl(src);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
QTextBrowser::setSource(src);
|
||||||
|
}
|
||||||
|
|
||||||
|
bool findText(const QString &text, QTextDocument::FindFlags flags, bool incremental, bool fromSearch)
|
||||||
|
{
|
||||||
|
QTextDocument *doc = document();
|
||||||
|
QTextCursor cursor = textCursor();
|
||||||
|
if (!doc || cursor.isNull())
|
||||||
|
return false;
|
||||||
|
|
||||||
|
const int position = cursor.selectionStart();
|
||||||
|
if (incremental)
|
||||||
|
cursor.setPosition(position);
|
||||||
|
|
||||||
|
QTextCursor found = doc->find(text, cursor, flags);
|
||||||
|
if (found.isNull()) {
|
||||||
|
if ((flags & QTextDocument::FindBackward) == 0)
|
||||||
|
cursor.movePosition(QTextCursor::Start);
|
||||||
|
else
|
||||||
|
cursor.movePosition(QTextCursor::End);
|
||||||
|
found = doc->find(text, cursor, flags);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (fromSearch) {
|
||||||
|
cursor.beginEditBlock();
|
||||||
|
viewport()->setUpdatesEnabled(false);
|
||||||
|
|
||||||
|
QTextCharFormat marker;
|
||||||
|
marker.setForeground(Qt::red);
|
||||||
|
marker.setBackground(Qt::yellow);
|
||||||
|
cursor.movePosition(QTextCursor::Start);
|
||||||
|
setTextCursor(cursor);
|
||||||
|
|
||||||
|
while (find(text)) {
|
||||||
|
QTextCursor hit = textCursor();
|
||||||
|
hit.mergeCharFormat(marker);
|
||||||
|
}
|
||||||
|
|
||||||
|
viewport()->setUpdatesEnabled(true);
|
||||||
|
cursor.endEditBlock();
|
||||||
|
}
|
||||||
|
|
||||||
|
bool cursorIsNull = found.isNull();
|
||||||
|
if (cursorIsNull) {
|
||||||
|
found = textCursor();
|
||||||
|
found.setPosition(position);
|
||||||
|
}
|
||||||
|
setTextCursor(found);
|
||||||
|
return !cursorIsNull;
|
||||||
|
}
|
||||||
|
|
||||||
|
private:
|
||||||
|
QHelpEngine *helpEngine_;
|
||||||
|
};
|
||||||
|
|
||||||
|
HelpBrowser::HelpBrowser(const QString &fileName)
|
||||||
|
: QMainWindow(NULL), fileName_(fileName), contentsCreated_(false)
|
||||||
|
{
|
||||||
|
settings_file();
|
||||||
|
|
||||||
|
QVBoxLayout *mainLayout = new QVBoxLayout;
|
||||||
|
mainLayout->setContentsMargins(0, 0, 0, 0);
|
||||||
|
mainLayout->setSpacing(0);
|
||||||
|
|
||||||
|
QToolBar *toolBar = new QToolBar(this);
|
||||||
|
QSplitter *splitter = new QSplitter(Qt::Horizontal, this);
|
||||||
|
|
||||||
|
QIcon icon = QIcon(":/images/back.png");
|
||||||
|
icon.addPixmap(QPixmap(":/images/back_hover.png"), QIcon::Active, QIcon::Off);
|
||||||
|
icon.addPixmap(QPixmap(":/images/back_disabled.png"), QIcon::Disabled, QIcon::Off);
|
||||||
|
backButton_ = new QAction(icon, QString::fromUtf8(language[lsBack].c_str()), this);
|
||||||
|
backButton_->setEnabled(false);
|
||||||
|
|
||||||
|
icon = QIcon(":/images/forward.png");
|
||||||
|
icon.addPixmap(QPixmap(":/images/forward_hover.png"), QIcon::Active, QIcon::Off);
|
||||||
|
icon.addPixmap(QPixmap(":/images/forward_disabled.png"), QIcon::Disabled, QIcon::Off);
|
||||||
|
fwdButton_ = new QAction(icon, QString::fromUtf8(language[lsForward].c_str()), this);
|
||||||
|
fwdButton_->setEnabled(false);
|
||||||
|
|
||||||
|
searchBox_ = new SearchLineEdit(this);
|
||||||
|
searchBox_->setFrame(false);
|
||||||
|
searchBox_->setFixedWidth(200);
|
||||||
|
searchBox_->setPlaceholderText(QString::fromUtf8(language[lsSearch].c_str()));
|
||||||
|
connect(searchBox_, SIGNAL(textChanged(const QString &)), this, SLOT(searchBoxChanged()));
|
||||||
|
connect(searchBox_, SIGNAL(returnPressed()), this, SLOT(searchBoxChanged()));
|
||||||
|
|
||||||
|
toolBar->setMovable(false);
|
||||||
|
toolBar->setIconSize(QSize(22, 22));
|
||||||
|
toolBar->addSeparator();
|
||||||
|
toolBar->addAction(backButton_);
|
||||||
|
toolBar->addAction(fwdButton_);
|
||||||
|
toolBar->addSeparator();
|
||||||
|
QWidget *spacer = new QWidget(this);
|
||||||
|
spacer->setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Preferred);
|
||||||
|
toolBar->addWidget(spacer);
|
||||||
|
toolBar->addWidget(searchBox_);
|
||||||
|
|
||||||
|
QVBoxLayout *vLayout = new QVBoxLayout(this);
|
||||||
|
vLayout->setContentsMargins(0, 0, 0, 0);
|
||||||
|
vLayout->setSpacing(0);
|
||||||
|
|
||||||
|
helpEngine_ = new QHelpEngine(fileName_, splitter);
|
||||||
|
connect(helpEngine_->contentModel(), SIGNAL(contentsCreated()), this, SLOT(contentsCreated()));
|
||||||
|
if (!helpEngine_->setupData()) {
|
||||||
|
contentsCreated_ = true;
|
||||||
|
MessageDialog::critical(this, QString("Can not open file \"%1\"").arg(fileName_), QMessageBox::Ok);
|
||||||
|
}
|
||||||
|
|
||||||
|
contentModel_ = new HelpContentModel(helpEngine_, this);
|
||||||
|
resultModel_ = new HelpResultModel(helpEngine_, this);
|
||||||
|
|
||||||
|
contentWidget_ = new TreeView(this);
|
||||||
|
contentWidget_->setObjectName("project");
|
||||||
|
contentWidget_->setFrameShape(QFrame::NoFrame);
|
||||||
|
contentWidget_->header()->setObjectName("project");
|
||||||
|
contentWidget_->setUniformRowHeights(true);
|
||||||
|
contentWidget_->setModel(contentModel_);
|
||||||
|
|
||||||
|
resultWidget_ = new TreeView(this);
|
||||||
|
resultWidget_->setObjectName("project");
|
||||||
|
resultWidget_->setFrameShape(QFrame::NoFrame);
|
||||||
|
resultWidget_->header()->setObjectName("project");
|
||||||
|
resultWidget_->setUniformRowHeights(true);
|
||||||
|
resultWidget_->setModel(resultModel_);
|
||||||
|
|
||||||
|
QToolButton *closeButton = new QToolButton(this);
|
||||||
|
closeButton->setObjectName("cancel");
|
||||||
|
closeButton->setToolTip(QString::fromUtf8(language[lsClose].c_str()));
|
||||||
|
|
||||||
|
QHBoxLayout *layout = new QHBoxLayout;
|
||||||
|
layout->setContentsMargins(5, 0, 5, 0);
|
||||||
|
layout->setSpacing(0);
|
||||||
|
layout->addWidget(closeButton, 0, Qt::AlignRight);
|
||||||
|
resultWidget_->header()->setLayout(layout);
|
||||||
|
|
||||||
|
tabWidget_ = new QStackedWidget;
|
||||||
|
tabWidget_->addWidget(contentWidget_);
|
||||||
|
tabWidget_->addWidget(resultWidget_);
|
||||||
|
|
||||||
|
splitter->addWidget(tabWidget_);
|
||||||
|
helpBrowser_ = new TextBrowser(helpEngine_);
|
||||||
|
helpBrowser_->setFrameShape(QFrame::NoFrame);
|
||||||
|
|
||||||
|
QWidget *right = new QWidget();
|
||||||
|
vLayout->addWidget(helpBrowser_);
|
||||||
|
findWidget_ = new FindWidget(this);
|
||||||
|
vLayout->addWidget(findWidget_);
|
||||||
|
findWidget_->hide();
|
||||||
|
right->setLayout(vLayout);
|
||||||
|
splitter->addWidget(right);
|
||||||
|
splitter->setStretchFactor(1, 1);
|
||||||
|
|
||||||
|
mainLayout->addWidget(toolBar);
|
||||||
|
mainLayout->addWidget(splitter);
|
||||||
|
|
||||||
|
QWidget *window = new QWidget();
|
||||||
|
window->setLayout(mainLayout);
|
||||||
|
setCentralWidget(window);
|
||||||
|
|
||||||
|
RemoteControl *rc = new RemoteControl(this);
|
||||||
|
connect(helpBrowser_, SIGNAL(sourceChanged(const QUrl &)), this, SLOT(syncTree(const QUrl &)));
|
||||||
|
connect(rc, SIGNAL(handleNavigateToKeywordCommand(const QString &)), this, SLOT(handleNavigateToKeywordCommand(const QString &)));
|
||||||
|
|
||||||
|
connect(contentWidget_, SIGNAL(clicked(const QModelIndex &)), this, SLOT(contentWidgetClicked(const QModelIndex &)));
|
||||||
|
connect(resultWidget_, SIGNAL(clicked(const QModelIndex &)), this, SLOT(resultWidgetClicked(const QModelIndex &)));
|
||||||
|
connect(backButton_, SIGNAL(triggered()), helpBrowser_, SLOT(backward()));
|
||||||
|
connect(fwdButton_, SIGNAL(triggered()), helpBrowser_, SLOT(forward()));
|
||||||
|
connect(helpBrowser_, SIGNAL(backwardAvailable(bool)), backButton_, SLOT(setEnabled(bool)));
|
||||||
|
connect(helpBrowser_, SIGNAL(forwardAvailable(bool)), fwdButton_, SLOT(setEnabled(bool)));
|
||||||
|
connect(helpBrowser_, SIGNAL(sourceChanged(const QUrl &)), this, SLOT(highlightSearchTerms()));
|
||||||
|
connect(resultModel_, SIGNAL(finished(int)), this, SLOT(searchingFinished()));
|
||||||
|
connect(closeButton, SIGNAL(clicked(bool)), this, SLOT(resultCloseClicked()));
|
||||||
|
|
||||||
|
connect(findWidget_, SIGNAL(findNext()), this, SLOT(findNext()));
|
||||||
|
connect(findWidget_, SIGNAL(findPrevious()), this, SLOT(findPrevious()));
|
||||||
|
connect(findWidget_, SIGNAL(find(QString, bool, bool)), this,
|
||||||
|
SLOT(find(QString, bool, bool)));
|
||||||
|
connect(findWidget_, SIGNAL(escapePressed()), helpBrowser_, SLOT(setFocus()));
|
||||||
|
|
||||||
|
resize(890, 440);
|
||||||
|
}
|
||||||
|
|
||||||
|
void HelpBrowser::handleNavigateToKeywordCommand(const QString &arg)
|
||||||
|
{
|
||||||
|
if(arg.length()) navigateToKeyword(arg);
|
||||||
|
raise();
|
||||||
|
activateWindow();
|
||||||
|
}
|
||||||
|
|
||||||
|
void HelpBrowser::findNext()
|
||||||
|
{
|
||||||
|
find(findWidget_->text(), true, false);
|
||||||
|
}
|
||||||
|
|
||||||
|
void HelpBrowser::findPrevious()
|
||||||
|
{
|
||||||
|
find(findWidget_->text(), false, false);
|
||||||
|
}
|
||||||
|
|
||||||
|
void HelpBrowser::find(const QString &ttf, bool forward, bool incremental)
|
||||||
|
{
|
||||||
|
bool found = false;
|
||||||
|
QTextDocument::FindFlags flags = (QTextDocument::FindFlags)0;
|
||||||
|
if (!forward)
|
||||||
|
flags |= QTextDocument::FindBackward;
|
||||||
|
if (findWidget_->caseSensitive())
|
||||||
|
flags |= QTextDocument::FindCaseSensitively;
|
||||||
|
found = helpBrowser_->findText(ttf, flags, incremental, false);
|
||||||
|
|
||||||
|
if (!found && ttf.isEmpty())
|
||||||
|
found = true; // the line edit is empty, no need to mark it red...
|
||||||
|
|
||||||
|
if (!findWidget_->isVisible())
|
||||||
|
findWidget_->show();
|
||||||
|
findWidget_->setPalette(found);
|
||||||
|
}
|
||||||
|
|
||||||
|
void HelpBrowser::highlightSearchTerms()
|
||||||
|
{
|
||||||
|
if (tabWidget_->currentIndex() != 1)
|
||||||
|
return;
|
||||||
|
|
||||||
|
QHelpSearchEngine *searchEngine = helpEngine_->searchEngine();
|
||||||
|
QList<QHelpSearchQuery> queryList = searchEngine->query();
|
||||||
|
|
||||||
|
QStringList terms;
|
||||||
|
foreach (const QHelpSearchQuery &query, queryList) {
|
||||||
|
switch (query.fieldName)
|
||||||
|
{
|
||||||
|
default: break;
|
||||||
|
case QHelpSearchQuery::ALL:
|
||||||
|
case QHelpSearchQuery::PHRASE:
|
||||||
|
case QHelpSearchQuery::DEFAULT:
|
||||||
|
case QHelpSearchQuery::ATLEAST:
|
||||||
|
foreach (QString term, query.wordList)
|
||||||
|
terms.append(term.remove(QLatin1Char('"')));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
foreach (const QString& term, terms)
|
||||||
|
helpBrowser_->findText(term, 0, false, true);
|
||||||
|
}
|
||||||
|
|
||||||
|
void HelpBrowser::keyPressEvent(QKeyEvent *e)
|
||||||
|
{
|
||||||
|
if ((e->modifiers() & Qt::ControlModifier) && e->key()==Qt::Key_F) {
|
||||||
|
if (!findWidget_->isVisible()) {
|
||||||
|
findWidget_->showAndClear(searchBox_->text());
|
||||||
|
} else {
|
||||||
|
findWidget_->show();
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
QWidget::keyPressEvent(e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void HelpBrowser::searchBoxChanged()
|
||||||
|
{
|
||||||
|
QString term = searchBox_->text();
|
||||||
|
if(term.length() < 3) {
|
||||||
|
tabWidget_->setCurrentIndex(0);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
resultModel_->search(term);
|
||||||
|
}
|
||||||
|
|
||||||
|
void HelpBrowser::searchingFinished()
|
||||||
|
{
|
||||||
|
tabWidget_->setCurrentIndex(1);
|
||||||
|
}
|
||||||
|
|
||||||
|
void HelpBrowser::syncTree(const QUrl &src)
|
||||||
|
{
|
||||||
|
setWindowTitle(QString("%1: %2").arg(QString::fromUtf8(language[lsHelp].c_str())).arg(helpBrowser_->documentTitle()));
|
||||||
|
|
||||||
|
// Synchronize with help content widget
|
||||||
|
QModelIndex indexOfSource = contentModel_->indexOf(src);
|
||||||
|
if (contentWidget_->currentIndex() != indexOfSource)
|
||||||
|
contentWidget_->setCurrentIndex(indexOfSource);
|
||||||
|
|
||||||
|
if(indexOfSource.isValid())
|
||||||
|
contentWidget_->expand(indexOfSource);
|
||||||
|
else
|
||||||
|
contentWidget_->expandAll();
|
||||||
|
}
|
||||||
|
|
||||||
|
static QString helpFileName(const QString &lang)
|
||||||
|
{
|
||||||
|
return QString("%1/Help/%2.qhc").arg(QCoreApplication::applicationDirPath()).arg(lang);
|
||||||
|
}
|
||||||
|
|
||||||
|
void HelpBrowser::showTopic(const QString &keywordId)
|
||||||
|
{
|
||||||
|
QString fileName = helpFileName(QString::fromUtf8(settings_file().language().c_str()));
|
||||||
|
if (!QFileInfo(fileName).exists())
|
||||||
|
fileName = helpFileName("en");
|
||||||
|
|
||||||
|
bool bOldProcess = true;
|
||||||
|
if (help_browser_process_ == NULL || help_browser_process_->state() == QProcess::NotRunning || help_browser_process_->fileName_ != fileName) {
|
||||||
|
delete help_browser_process_;
|
||||||
|
help_browser_process_ = new QHelpBrowserProcess(qApp, fileName);
|
||||||
|
if (!help_browser_process_->waitForStarted())
|
||||||
|
{
|
||||||
|
MessageDialog::critical(NULL, QString("Can not launch help system"), QMessageBox::Ok);
|
||||||
|
delete help_browser_process_;
|
||||||
|
help_browser_process_ = NULL;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
bOldProcess = false;
|
||||||
|
}
|
||||||
|
QByteArray ba;
|
||||||
|
ba += "navigateToKeyword#";
|
||||||
|
ba += (keywordId.length() || bOldProcess) ? keywordId : QString("default");
|
||||||
|
ba += ";\n";
|
||||||
|
help_browser_process_->write(ba);
|
||||||
|
}
|
||||||
|
|
||||||
|
void HelpBrowser::navigateToKeyword(const QString &keywordId)
|
||||||
|
{
|
||||||
|
for (int i = 0; i < 50 && !contentsCreated_; i++)
|
||||||
|
QCoreApplication::processEvents(QEventLoop::AllEvents, 100);
|
||||||
|
if(!helpBrowser_->navigateToKeyword(keywordId))
|
||||||
|
MessageDialog::critical(this, QString("Can not find keyword \"%1\" for \"%2\"").arg(keywordId, fileName_), QMessageBox::Ok);
|
||||||
|
}
|
||||||
|
|
||||||
|
void HelpBrowser::contentWidgetClicked(const QModelIndex &index)
|
||||||
|
{
|
||||||
|
QHelpContentItem *item = contentModel_->contentItemAt(index);
|
||||||
|
if (!item)
|
||||||
|
return;
|
||||||
|
|
||||||
|
QUrl url = item->url();
|
||||||
|
if (url.isValid())
|
||||||
|
helpBrowser_->setSource(url);
|
||||||
|
}
|
||||||
|
|
||||||
|
void HelpBrowser::resultWidgetClicked(const QModelIndex &index)
|
||||||
|
{
|
||||||
|
HelpResultItem *item = resultModel_->itemAt(index);
|
||||||
|
if (!item)
|
||||||
|
return;
|
||||||
|
|
||||||
|
QUrl url = item->url();
|
||||||
|
if (url.isValid())
|
||||||
|
helpBrowser_->setSource(url);
|
||||||
|
}
|
||||||
|
|
||||||
|
void HelpBrowser::pathClicked(const QString &link)
|
||||||
|
{
|
||||||
|
helpBrowser_->setSource(link);
|
||||||
|
}
|
||||||
|
|
||||||
|
void HelpBrowser::resultCloseClicked()
|
||||||
|
{
|
||||||
|
searchBox_->clear();
|
||||||
|
}
|
||||||
|
|
||||||
|
void HelpBrowser::contentsCreated()
|
||||||
|
{
|
||||||
|
contentsCreated_ = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* QHelpBrowserProcess
|
||||||
|
*/
|
||||||
|
|
||||||
|
QHelpBrowserProcess *HelpBrowser::help_browser_process_;
|
||||||
|
|
||||||
|
QHelpBrowserProcess::QHelpBrowserProcess(QObject *parent, const QString &fileName) : QProcess(parent), fileName_(fileName)
|
||||||
|
{
|
||||||
|
QStringList args;
|
||||||
|
args << "--help" << fileName;
|
||||||
|
start(QCoreApplication::applicationFilePath(), args);
|
||||||
|
}
|
||||||
|
|
||||||
|
QHelpBrowserProcess::~QHelpBrowserProcess()
|
||||||
|
{
|
||||||
|
if(state() != NotRunning)
|
||||||
|
kill();
|
||||||
|
}
|
125
VMProtect/help_browser.h
Normal file
@ -0,0 +1,125 @@
|
|||||||
|
#ifndef HELP_BROWSER_H
|
||||||
|
#define HELP_BROWSER_H
|
||||||
|
|
||||||
|
class TextBrowser;
|
||||||
|
class QHelpEngine;
|
||||||
|
class QHelpSearchEngine;
|
||||||
|
class QPushButton;
|
||||||
|
class SearchLineEdit;
|
||||||
|
class QHelpContentItem;
|
||||||
|
class FindWidget;
|
||||||
|
|
||||||
|
class HelpContentModel : public QIdentityProxyModel
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
HelpContentModel(QHelpEngine *engine, QObject *parent = 0);
|
||||||
|
virtual QVariant data(const QModelIndex &index, int role) const;
|
||||||
|
virtual QVariant headerData(int section, Qt::Orientation orientation, int role) const;
|
||||||
|
QHelpContentItem *contentItemAt(const QModelIndex &index) const;
|
||||||
|
QModelIndex indexOf(const QUrl &link);
|
||||||
|
private:
|
||||||
|
QModelIndex searchContentItem(const QModelIndex &parent, const QString &path);
|
||||||
|
};
|
||||||
|
|
||||||
|
class HelpResultItem
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
HelpResultItem(const QString &title, const QString &url, const QString &toolTip);
|
||||||
|
~HelpResultItem();
|
||||||
|
QString title() const { return title_; }
|
||||||
|
QString url() const { return url_; }
|
||||||
|
QString toolTip() const { return toolTip_; }
|
||||||
|
HelpResultItem *child(int index) const { return children_.value(index); };
|
||||||
|
int childCount() const { return children_.size(); }
|
||||||
|
QList<HelpResultItem *> children() const { return children_; };
|
||||||
|
HelpResultItem *parent() const { return parent_; };
|
||||||
|
void clear();
|
||||||
|
void addChild(HelpResultItem *child);
|
||||||
|
void insertChild(int index, HelpResultItem *child);
|
||||||
|
void removeChild(HelpResultItem *child);
|
||||||
|
private:
|
||||||
|
HelpResultItem *parent_;
|
||||||
|
QString title_;
|
||||||
|
QString url_;
|
||||||
|
QString toolTip_;
|
||||||
|
QList<HelpResultItem *> children_;
|
||||||
|
};
|
||||||
|
|
||||||
|
class HelpResultModel : public QAbstractItemModel
|
||||||
|
{
|
||||||
|
Q_OBJECT
|
||||||
|
public:
|
||||||
|
HelpResultModel(QHelpEngine *engine, QObject *parent = 0);
|
||||||
|
~HelpResultModel();
|
||||||
|
void search(const QString &text);
|
||||||
|
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) const;
|
||||||
|
virtual int columnCount(const QModelIndex &parent) const;
|
||||||
|
virtual QVariant data(const QModelIndex &index, int role) const;
|
||||||
|
virtual QVariant headerData(int section, Qt::Orientation orientation, int role) const;
|
||||||
|
HelpResultItem *itemAt(const QModelIndex &index) const;
|
||||||
|
signals:
|
||||||
|
void finished(int hits);
|
||||||
|
protected slots:
|
||||||
|
void searchingFinished();
|
||||||
|
private:
|
||||||
|
QHelpEngine *engine_;
|
||||||
|
HelpResultItem *root_;
|
||||||
|
};
|
||||||
|
|
||||||
|
class QHelpBrowserProcess : public QProcess
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
QHelpBrowserProcess(QObject *parent, const QString &fileName);
|
||||||
|
const QString fileName_;
|
||||||
|
~QHelpBrowserProcess();
|
||||||
|
};
|
||||||
|
|
||||||
|
class RemoteControl;
|
||||||
|
class HelpBrowser : public QMainWindow
|
||||||
|
{
|
||||||
|
Q_OBJECT
|
||||||
|
public:
|
||||||
|
HelpBrowser(const QString &fileName);
|
||||||
|
static void showTopic(const QString &keywordId);
|
||||||
|
|
||||||
|
private:
|
||||||
|
void navigateToKeyword(const QString &keywordId);
|
||||||
|
void keyPressEvent(QKeyEvent *e);
|
||||||
|
void updatePath();
|
||||||
|
|
||||||
|
static QHelpBrowserProcess *help_browser_process_;
|
||||||
|
|
||||||
|
QString fileName_;
|
||||||
|
QHelpEngine *helpEngine_;
|
||||||
|
TextBrowser *helpBrowser_;
|
||||||
|
QAction *backButton_;
|
||||||
|
QAction *fwdButton_;
|
||||||
|
SearchLineEdit *searchBox_;
|
||||||
|
QStackedWidget *tabWidget_;
|
||||||
|
FindWidget *findWidget_;
|
||||||
|
QTreeView *contentWidget_;
|
||||||
|
QTreeView *resultWidget_;
|
||||||
|
HelpContentModel *contentModel_;
|
||||||
|
HelpResultModel *resultModel_;
|
||||||
|
RemoteControl *rc_;
|
||||||
|
bool contentsCreated_;
|
||||||
|
|
||||||
|
protected Q_SLOTS:
|
||||||
|
void syncTree(const QUrl &);
|
||||||
|
void searchBoxChanged();
|
||||||
|
void searchingFinished();
|
||||||
|
void highlightSearchTerms();
|
||||||
|
void findNext();
|
||||||
|
void findPrevious();
|
||||||
|
void find(const QString &ttf, bool forward, bool incremental);
|
||||||
|
void contentWidgetClicked(const QModelIndex &index);
|
||||||
|
void resultWidgetClicked(const QModelIndex &index);
|
||||||
|
void pathClicked(const QString &link);
|
||||||
|
void resultCloseClicked();
|
||||||
|
void contentsCreated();
|
||||||
|
void handleNavigateToKeywordCommand(const QString &arg);
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif
|
BIN
VMProtect/images/add.png
Normal file
After Width: | Height: | Size: 15 KiB |
BIN
VMProtect/images/add_disabled.png
Normal file
After Width: | Height: | Size: 16 KiB |
BIN
VMProtect/images/add_gray.png
Normal file
After Width: | Height: | Size: 15 KiB |
BIN
VMProtect/images/add_hover.png
Normal file
After Width: | Height: | Size: 15 KiB |
BIN
VMProtect/images/back.png
Normal file
After Width: | Height: | Size: 16 KiB |
BIN
VMProtect/images/back_disabled.png
Normal file
After Width: | Height: | Size: 15 KiB |
BIN
VMProtect/images/back_hover.png
Normal file
After Width: | Height: | Size: 16 KiB |
BIN
VMProtect/images/boot_examples.png
Normal file
After Width: | Height: | Size: 14 KiB |
BIN
VMProtect/images/boot_help.png
Normal file
After Width: | Height: | Size: 527 B |
BIN
VMProtect/images/boot_open.png
Normal file
After Width: | Height: | Size: 412 B |
BIN
VMProtect/images/box.png
Normal file
After Width: | Height: | Size: 327 B |
BIN
VMProtect/images/branch_closed.png
Normal file
After Width: | Height: | Size: 231 B |
BIN
VMProtect/images/branch_open.png
Normal file
After Width: | Height: | Size: 213 B |
BIN
VMProtect/images/browse.png
Normal file
After Width: | Height: | Size: 240 B |
BIN
VMProtect/images/bullet_delete.png
Normal file
After Width: | Height: | Size: 227 B |
BIN
VMProtect/images/bullet_import.png
Normal file
After Width: | Height: | Size: 480 B |
BIN
VMProtect/images/bullet_key.png
Normal file
After Width: | Height: | Size: 254 B |
BIN
VMProtect/images/bullet_link.png
Normal file
After Width: | Height: | Size: 560 B |
BIN
VMProtect/images/bullet_warning.png
Normal file
After Width: | Height: | Size: 249 B |
BIN
VMProtect/images/calc.png
Normal file
After Width: | Height: | Size: 18 KiB |
BIN
VMProtect/images/cancel.png
Normal file
After Width: | Height: | Size: 537 B |
BIN
VMProtect/images/cancel_gray.png
Normal file
After Width: | Height: | Size: 15 KiB |
BIN
VMProtect/images/cancel_hover.png
Normal file
After Width: | Height: | Size: 533 B |
BIN
VMProtect/images/check_off.png
Normal file
After Width: | Height: | Size: 15 KiB |
BIN
VMProtect/images/check_off_hover.png
Normal file
After Width: | Height: | Size: 15 KiB |
BIN
VMProtect/images/check_on.png
Normal file
After Width: | Height: | Size: 15 KiB |
BIN
VMProtect/images/check_on_hover.png
Normal file
After Width: | Height: | Size: 15 KiB |
BIN
VMProtect/images/checkbox.png
Normal file
After Width: | Height: | Size: 173 B |
BIN
VMProtect/images/checkbox_checked.png
Normal file
After Width: | Height: | Size: 350 B |
BIN
VMProtect/images/code.png
Normal file
After Width: | Height: | Size: 362 B |
BIN
VMProtect/images/compile.png
Normal file
After Width: | Height: | Size: 295 B |
BIN
VMProtect/images/compile_disabled.png
Normal file
After Width: | Height: | Size: 294 B |
BIN
VMProtect/images/compile_hover.png
Normal file
After Width: | Height: | Size: 300 B |
BIN
VMProtect/images/copy.png
Normal file
After Width: | Height: | Size: 223 B |
BIN
VMProtect/images/copy_disabled.png
Normal file
After Width: | Height: | Size: 228 B |
BIN
VMProtect/images/copy_hover.png
Normal file
After Width: | Height: | Size: 223 B |
BIN
VMProtect/images/cut.png
Normal file
After Width: | Height: | Size: 467 B |
BIN
VMProtect/images/cut_disabled.png
Normal file
After Width: | Height: | Size: 437 B |
BIN
VMProtect/images/cut_hover.png
Normal file
After Width: | Height: | Size: 468 B |
BIN
VMProtect/images/database.png
Normal file
After Width: | Height: | Size: 474 B |
BIN
VMProtect/images/database_export.png
Normal file
After Width: | Height: | Size: 907 B |
BIN
VMProtect/images/database_import.png
Normal file
After Width: | Height: | Size: 923 B |
BIN
VMProtect/images/delete.png
Normal file
After Width: | Height: | Size: 695 B |
BIN
VMProtect/images/details.png
Normal file
After Width: | Height: | Size: 1.1 KiB |
BIN
VMProtect/images/details_checked.png
Normal file
After Width: | Height: | Size: 1.7 KiB |
BIN
VMProtect/images/details_hover.png
Normal file
After Width: | Height: | Size: 928 B |
BIN
VMProtect/images/disabled.png
Normal file
After Width: | Height: | Size: 361 B |
BIN
VMProtect/images/disk.png
Normal file
After Width: | Height: | Size: 300 B |
BIN
VMProtect/images/disk_disabled.png
Normal file
After Width: | Height: | Size: 293 B |
BIN
VMProtect/images/disk_hover.png
Normal file
After Width: | Height: | Size: 299 B |
BIN
VMProtect/images/down_arrow.png
Normal file
After Width: | Height: | Size: 176 B |
BIN
VMProtect/images/down_arrow_checked.png
Normal file
After Width: | Height: | Size: 215 B |
BIN
VMProtect/images/down_arrow_disabled.png
Normal file
After Width: | Height: | Size: 184 B |
BIN
VMProtect/images/down_arrow_hover.png
Normal file
After Width: | Height: | Size: 235 B |
BIN
VMProtect/images/dump.png
Normal file
After Width: | Height: | Size: 15 KiB |
BIN
VMProtect/images/error.png
Normal file
After Width: | Height: | Size: 394 B |
BIN
VMProtect/images/execute.png
Normal file
After Width: | Height: | Size: 310 B |
BIN
VMProtect/images/execute_disabled.png
Normal file
After Width: | Height: | Size: 306 B |
BIN
VMProtect/images/execute_hover.png
Normal file
After Width: | Height: | Size: 317 B |
BIN
VMProtect/images/export.png
Normal file
After Width: | Height: | Size: 1.2 KiB |
BIN
VMProtect/images/file_open.png
Normal file
After Width: | Height: | Size: 283 B |
BIN
VMProtect/images/file_open_hover.png
Normal file
After Width: | Height: | Size: 290 B |
BIN
VMProtect/images/folder.png
Normal file
After Width: | Height: | Size: 383 B |
BIN
VMProtect/images/folder_close.png
Normal file
After Width: | Height: | Size: 282 B |
BIN
VMProtect/images/forward.png
Normal file
After Width: | Height: | Size: 16 KiB |
BIN
VMProtect/images/forward_disabled.png
Normal file
After Width: | Height: | Size: 15 KiB |
BIN
VMProtect/images/forward_hover.png
Normal file
After Width: | Height: | Size: 16 KiB |
BIN
VMProtect/images/functions.png
Normal file
After Width: | Height: | Size: 1.1 KiB |
BIN
VMProtect/images/functions_checked.png
Normal file
After Width: | Height: | Size: 1.7 KiB |
BIN
VMProtect/images/functions_hover.png
Normal file
After Width: | Height: | Size: 993 B |
BIN
VMProtect/images/gear.png
Normal file
After Width: | Height: | Size: 462 B |
BIN
VMProtect/images/goto.png
Normal file
After Width: | Height: | Size: 15 KiB |
BIN
VMProtect/images/goto_disabled.png
Normal file
After Width: | Height: | Size: 15 KiB |
BIN
VMProtect/images/goto_hover.png
Normal file
After Width: | Height: | Size: 15 KiB |
BIN
VMProtect/images/help_gray.png
Normal file
After Width: | Height: | Size: 18 KiB |
BIN
VMProtect/images/help_icon.png
Normal file
After Width: | Height: | Size: 35 KiB |
BIN
VMProtect/images/import.png
Normal file
After Width: | Height: | Size: 357 B |
BIN
VMProtect/images/information.png
Normal file
After Width: | Height: | Size: 764 B |
BIN
VMProtect/images/item.png
Normal file
After Width: | Height: | Size: 265 B |
BIN
VMProtect/images/item_code.png
Normal file
After Width: | Height: | Size: 15 KiB |
BIN
VMProtect/images/item_export.png
Normal file
After Width: | Height: | Size: 415 B |
BIN
VMProtect/images/item_file.png
Normal file
After Width: | Height: | Size: 14 KiB |