|
@ -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/
|
|
@ -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>
|
|
@ -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>
|
|
@ -0,0 +1,4 @@
|
|||
需要修复:
|
||||
|
||||
_CxxThrowException
|
||||
返回地址必须填充Nop否则会出错
|
|
@ -0,0 +1,10 @@
|
|||
VMProtect project
|
||||
-----------------
|
||||
|
||||
Building
|
||||
|
||||
POSIX:
|
||||
$ ./build.sh
|
||||
|
||||
Windows:
|
||||
> build.bat
|
|
@ -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");
|
||||
}
|
|
@ -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
|
|
@ -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];
|
||||
}
|
||||
|
|
@ -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
|
|
@ -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,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
|
|
@ -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
|
|
@ -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
|
|
@ -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);
|
||||
}
|
|
@ -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
|
|
@ -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();
|
||||
}
|
|
@ -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
|
After Width: | Height: | Size: 15 KiB |
After Width: | Height: | Size: 16 KiB |
After Width: | Height: | Size: 15 KiB |
After Width: | Height: | Size: 15 KiB |
After Width: | Height: | Size: 16 KiB |
After Width: | Height: | Size: 15 KiB |
After Width: | Height: | Size: 16 KiB |
After Width: | Height: | Size: 14 KiB |
After Width: | Height: | Size: 527 B |
After Width: | Height: | Size: 412 B |
After Width: | Height: | Size: 327 B |
After Width: | Height: | Size: 231 B |
After Width: | Height: | Size: 213 B |
After Width: | Height: | Size: 240 B |
After Width: | Height: | Size: 227 B |
After Width: | Height: | Size: 480 B |
After Width: | Height: | Size: 254 B |
After Width: | Height: | Size: 560 B |
After Width: | Height: | Size: 249 B |
After Width: | Height: | Size: 18 KiB |
After Width: | Height: | Size: 537 B |
After Width: | Height: | Size: 15 KiB |
After Width: | Height: | Size: 533 B |
After Width: | Height: | Size: 15 KiB |
After Width: | Height: | Size: 15 KiB |
After Width: | Height: | Size: 15 KiB |
After Width: | Height: | Size: 15 KiB |
After Width: | Height: | Size: 173 B |
After Width: | Height: | Size: 350 B |
After Width: | Height: | Size: 362 B |
After Width: | Height: | Size: 295 B |
After Width: | Height: | Size: 294 B |
After Width: | Height: | Size: 300 B |
After Width: | Height: | Size: 223 B |
After Width: | Height: | Size: 228 B |
After Width: | Height: | Size: 223 B |
After Width: | Height: | Size: 467 B |
After Width: | Height: | Size: 437 B |
After Width: | Height: | Size: 468 B |
After Width: | Height: | Size: 474 B |
After Width: | Height: | Size: 907 B |
After Width: | Height: | Size: 923 B |
After Width: | Height: | Size: 695 B |
After Width: | Height: | Size: 1.1 KiB |
After Width: | Height: | Size: 1.7 KiB |
After Width: | Height: | Size: 928 B |
After Width: | Height: | Size: 361 B |
After Width: | Height: | Size: 300 B |
After Width: | Height: | Size: 293 B |
After Width: | Height: | Size: 299 B |
After Width: | Height: | Size: 176 B |
After Width: | Height: | Size: 215 B |
After Width: | Height: | Size: 184 B |
After Width: | Height: | Size: 235 B |
After Width: | Height: | Size: 15 KiB |
After Width: | Height: | Size: 394 B |
After Width: | Height: | Size: 310 B |
After Width: | Height: | Size: 306 B |
After Width: | Height: | Size: 317 B |
After Width: | Height: | Size: 1.2 KiB |
After Width: | Height: | Size: 283 B |
After Width: | Height: | Size: 290 B |
After Width: | Height: | Size: 383 B |
After Width: | Height: | Size: 282 B |
After Width: | Height: | Size: 16 KiB |
After Width: | Height: | Size: 15 KiB |
After Width: | Height: | Size: 16 KiB |
After Width: | Height: | Size: 1.1 KiB |
After Width: | Height: | Size: 1.7 KiB |
After Width: | Height: | Size: 993 B |
After Width: | Height: | Size: 462 B |
After Width: | Height: | Size: 15 KiB |
After Width: | Height: | Size: 15 KiB |
After Width: | Height: | Size: 15 KiB |
After Width: | Height: | Size: 18 KiB |
After Width: | Height: | Size: 35 KiB |
After Width: | Height: | Size: 357 B |
After Width: | Height: | Size: 764 B |
After Width: | Height: | Size: 265 B |
After Width: | Height: | Size: 15 KiB |
After Width: | Height: | Size: 415 B |
After Width: | Height: | Size: 14 KiB |