mirror of
https://github.com/rizinorg/cutter.git
synced 2024-12-18 10:56:11 +00:00
Working open dialog with waiting dialog.
This commit is contained in:
parent
439b268927
commit
5e2d58ea11
@ -30,6 +30,7 @@ option(CUTTER_PACKAGE_RZ_LIBYARA "Compile and install rz-libyara during the inst
|
||||
option(CUTTER_PACKAGE_RZ_SILHOUETTE "Compile and install rz-silhouette during the install step." OFF)
|
||||
option(CUTTER_PACKAGE_JSDEC "Compile and install jsdec during install step." OFF)
|
||||
OPTION(CUTTER_QT6 "Use QT6" OFF)
|
||||
OPTION(CUTTER_ASAN "Build with ASAN" OFF)
|
||||
|
||||
if(NOT CUTTER_ENABLE_PYTHON)
|
||||
set(CUTTER_ENABLE_PYTHON_BINDINGS OFF)
|
||||
@ -188,6 +189,7 @@ message(STATUS "- Package RzLibYara: ${CUTTER_PACKAGE_RZ_LIBYARA}")
|
||||
message(STATUS "- Package RzSilhouette: ${CUTTER_PACKAGE_RZ_SILHOUETTE}")
|
||||
message(STATUS "- Package JSDec: ${CUTTER_PACKAGE_JSDEC}")
|
||||
message(STATUS "- QT6: ${CUTTER_QT6}")
|
||||
message(STATUS "- ASAN: ${CUTTER_ASAN}")
|
||||
message(STATUS "")
|
||||
|
||||
add_subdirectory(src)
|
||||
|
@ -157,6 +157,7 @@ set(SOURCES
|
||||
tools/basefind/BaseFindSearchDialog.cpp
|
||||
tools/basefind/BaseFindResultsDialog.cpp
|
||||
tools/bindiff/DiffLoadDialog.cpp
|
||||
tools/bindiff/DiffWaitDialog.cpp
|
||||
)
|
||||
set(HEADER_FILES
|
||||
core/Cutter.h
|
||||
@ -323,6 +324,7 @@ set(HEADER_FILES
|
||||
tools/basefind/BaseFindSearchDialog.h
|
||||
tools/basefind/BaseFindResultsDialog.h
|
||||
tools/bindiff/DiffLoadDialog.h
|
||||
tools/bindiff/DiffWaitDialog.h
|
||||
)
|
||||
set(UI_FILES
|
||||
dialogs/AboutDialog.ui
|
||||
@ -398,6 +400,7 @@ set(UI_FILES
|
||||
tools/basefind/BaseFindSearchDialog.ui
|
||||
tools/basefind/BaseFindResultsDialog.ui
|
||||
tools/bindiff/DiffLoadDialog.ui
|
||||
tools/bindiff/DiffWaitDialog.ui
|
||||
)
|
||||
set(QRC_FILES
|
||||
resources.qrc
|
||||
@ -588,6 +591,12 @@ if(CUTTER_ENABLE_PACKAGING)
|
||||
target_compile_definitions(Cutter PRIVATE CUTTER_ENABLE_PACKAGING)
|
||||
endif()
|
||||
|
||||
if(CUTTER_ASAN)
|
||||
set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -fdiagnostics-color=always -fsanitize=address,undefined -fno-omit-frame-pointer -fsanitize-address-use-after-scope")
|
||||
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -fdiagnostics-color=always -fsanitize=address,undefined -fno-omit-frame-pointer -fsanitize-address-use-after-scope")
|
||||
set(CMAKE_LINKER_FLAGS "${CMAKE_LINKER_FLAGS} -fdiagnostics-color=always -fsanitize=address,undefined -fno-omit-frame-pointer -fsanitize-address-use-after-scope")
|
||||
endif()
|
||||
|
||||
include(Translations)
|
||||
|
||||
# Install files
|
||||
|
@ -6,10 +6,9 @@ bool BinDiff::threadCallback(const size_t nLeft, const size_t nMatch, void *user
|
||||
return bdiff->updateProgress(nLeft, nMatch);
|
||||
}
|
||||
|
||||
BinDiff::BinDiff(CutterCore *core)
|
||||
: core(core),
|
||||
result(nullptr),
|
||||
continue_run(true),
|
||||
BinDiff::BinDiff()
|
||||
: result(nullptr),
|
||||
continueRun(true),
|
||||
maxTotal(1)
|
||||
#if QT_VERSION < QT_VERSION_CHECK(5, 14, 0)
|
||||
,
|
||||
@ -20,31 +19,48 @@ BinDiff::BinDiff(CutterCore *core)
|
||||
|
||||
BinDiff::~BinDiff()
|
||||
{
|
||||
cancel();
|
||||
wait();
|
||||
rz_analysis_match_result_free(result);
|
||||
}
|
||||
|
||||
void BinDiff::run(QString fileName)
|
||||
void BinDiff::setFile(QString filePath)
|
||||
{
|
||||
mutex.lock();
|
||||
file = filePath;
|
||||
mutex.unlock();
|
||||
}
|
||||
|
||||
void BinDiff::setAnalysisLevel(int aLevel)
|
||||
{
|
||||
mutex.lock();
|
||||
level = aLevel;
|
||||
mutex.unlock();
|
||||
}
|
||||
|
||||
void BinDiff::run()
|
||||
{
|
||||
qRegisterMetaType<BinDiffStatusDescription>();
|
||||
|
||||
mutex.lock();
|
||||
rz_analysis_match_result_free(result);
|
||||
result = nullptr;
|
||||
continue_run = true;
|
||||
continueRun = true;
|
||||
maxTotal = 1; // maxTotal must be at least 1.
|
||||
mutex.unlock();
|
||||
|
||||
core->coreMutex.lock();
|
||||
result = core->diffNewFile(fileName, threadCallback, this);
|
||||
core->coreMutex.unlock();
|
||||
result = Core()->diffNewFile(file, level, threadCallback, this);
|
||||
|
||||
emit complete();
|
||||
mutex.lock();
|
||||
bool canComplete = continueRun;
|
||||
mutex.unlock();
|
||||
if (canComplete) {
|
||||
emit complete();
|
||||
}
|
||||
}
|
||||
|
||||
void BinDiff::cancel()
|
||||
{
|
||||
mutex.lock();
|
||||
continue_run = false;
|
||||
continueRun = false;
|
||||
mutex.unlock();
|
||||
}
|
||||
|
||||
@ -69,6 +85,10 @@ QList<BinDiffMatchDescription> BinDiff::matches()
|
||||
const RzAnalysisFunction *fcn_a = nullptr;
|
||||
const RzAnalysisFunction *fcn_b = nullptr;
|
||||
|
||||
if (!result) {
|
||||
return pairs;
|
||||
}
|
||||
|
||||
CutterRzListForeach (result->matches, it, RzAnalysisMatchPair, pair) {
|
||||
BinDiffMatchDescription desc;
|
||||
fcn_a = static_cast<const RzAnalysisFunction *>(pair->pair_a);
|
||||
@ -93,6 +113,10 @@ QList<FunctionDescription> BinDiff::mismatch(bool fileA)
|
||||
RzList *unmatch = fileA ? result->unmatch_a : result->unmatch_b;
|
||||
RzListIter *it = nullptr;
|
||||
|
||||
if (!result) {
|
||||
return list;
|
||||
}
|
||||
|
||||
CutterRzListForeach (unmatch, it, RzAnalysisFunction, func) {
|
||||
FunctionDescription desc;
|
||||
setFunctionDescription(&desc, func);
|
||||
@ -102,19 +126,23 @@ QList<FunctionDescription> BinDiff::mismatch(bool fileA)
|
||||
return list;
|
||||
}
|
||||
|
||||
bool BinDiff::updateProgress(const size_t nLeft, const size_t nMatch)
|
||||
bool BinDiff::updateProgress(size_t nLeft, size_t nMatch)
|
||||
{
|
||||
mutex.lock();
|
||||
|
||||
if (maxTotal < nMatch) {
|
||||
if (nMatch > maxTotal) {
|
||||
maxTotal = nMatch;
|
||||
}
|
||||
if (maxTotal < nLeft) {
|
||||
if (nLeft > maxTotal) {
|
||||
maxTotal = nLeft;
|
||||
}
|
||||
|
||||
emit progress(maxTotal, nLeft, nMatch);
|
||||
bool ret = continue_run;
|
||||
BinDiffStatusDescription status;
|
||||
status.total = maxTotal;
|
||||
status.nLeft = nLeft;
|
||||
status.nMatch = nMatch;
|
||||
|
||||
emit progress(status);
|
||||
bool ret = continueRun;
|
||||
mutex.unlock();
|
||||
return ret;
|
||||
}
|
||||
|
@ -8,17 +8,19 @@
|
||||
#include "CutterDescriptions.h"
|
||||
#include <rz_analysis.h>
|
||||
|
||||
class CutterCore;
|
||||
|
||||
class BinDiff : public QThread
|
||||
{
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
explicit BinDiff(CutterCore *core);
|
||||
explicit BinDiff();
|
||||
virtual ~BinDiff();
|
||||
|
||||
void run(QString fileName);
|
||||
void run();
|
||||
|
||||
void setFile(QString filePth);
|
||||
void setAnalysisLevel(int aLevel);
|
||||
|
||||
QList<BinDiffMatchDescription> matches();
|
||||
QList<FunctionDescription> mismatch(bool fileA);
|
||||
|
||||
@ -26,19 +28,20 @@ public slots:
|
||||
void cancel();
|
||||
|
||||
signals:
|
||||
void progress(const size_t total, const size_t nLeft, const size_t nMatch);
|
||||
void progress(BinDiffStatusDescription status);
|
||||
void complete();
|
||||
|
||||
private:
|
||||
CutterCore *const core;
|
||||
RzAnalysisMatchResult *result;
|
||||
bool continue_run;
|
||||
bool continueRun;
|
||||
size_t maxTotal;
|
||||
#if QT_VERSION < QT_VERSION_CHECK(5, 14, 0)
|
||||
QMutex mutex;
|
||||
#else
|
||||
QRecursiveMutex mutex;
|
||||
#endif
|
||||
QString file;
|
||||
int level;
|
||||
|
||||
bool updateProgress(const size_t nLeft, const size_t nMatch);
|
||||
static bool threadCallback(const size_t nLeft, const size_t nMatch, void *user);
|
||||
|
@ -233,11 +233,11 @@ CutterCore::~CutterCore()
|
||||
{
|
||||
delete bbHighlighter;
|
||||
rz_cons_sleep_end(coreBed);
|
||||
rz_core_free(this->core_b);
|
||||
this->core_b = nullptr;
|
||||
rz_core_task_sync_end(&core_a->tasks);
|
||||
rz_core_free(this->core_a);
|
||||
this->core_a = nullptr;
|
||||
rz_core_free(this->core_b);
|
||||
this->core_b = nullptr;
|
||||
rz_cons_free();
|
||||
assert(uniqueInstance == this);
|
||||
uniqueInstance = nullptr;
|
||||
@ -4564,30 +4564,28 @@ bool CutterCore::isWriteModeEnabled()
|
||||
return false;
|
||||
}
|
||||
|
||||
RzAnalysisMatchResult *CutterCore::diffNewFile(const QString &filePath,
|
||||
RzAnalysisMatchResult *CutterCore::diffNewFile(const QString &filePath, int level,
|
||||
RzAnalysisMatchThreadInfoCb callback, void *user)
|
||||
{
|
||||
CORE_LOCK();
|
||||
RzList *fcns_a = nullptr, *fcns_b = nullptr;
|
||||
RzAnalysisMatchResult *result = nullptr;
|
||||
RzAnalysisMatchOpt opts;
|
||||
RzListIter *iter;
|
||||
RzConfigNode *node;
|
||||
void *ptr;
|
||||
|
||||
if (core_b) {
|
||||
rz_core_free(core_b);
|
||||
core_b = nullptr;
|
||||
}
|
||||
|
||||
core_b = rz_core_new();
|
||||
if (!core_b) {
|
||||
goto fail;
|
||||
// FIXME: allocating and deallocating a new core here, taints some pointer on core_a
|
||||
core_b = rz_core_new();
|
||||
if (!core_b) {
|
||||
return nullptr;
|
||||
}
|
||||
rz_config_set_b(core_b->config, "io.va", rz_config_get_b(core_a->config, "io.va"));
|
||||
|
||||
rz_core_loadlibs(core_b, RZ_CORE_LOADLIBS_ALL);
|
||||
core_b->print->scr_prompt = false;
|
||||
}
|
||||
|
||||
rz_config_set_b(core_b->config, "io.va", rz_config_get_b(core_a->config, "io.va"));
|
||||
|
||||
rz_core_loadlibs(core_b, RZ_CORE_LOADLIBS_ALL);
|
||||
core_b->print->scr_prompt = false;
|
||||
if (!rz_core_file_open(core_b, filePath.toUtf8().constData(), RZ_PERM_RX, 0)) {
|
||||
qWarning() << "cannot open file " << filePath;
|
||||
goto fail;
|
||||
@ -4603,9 +4601,7 @@ RzAnalysisMatchResult *CutterCore::diffNewFile(const QString &filePath,
|
||||
goto fail;
|
||||
}
|
||||
|
||||
rz_list_foreach(core_a->config->nodes, iter, ptr)
|
||||
{
|
||||
node = reinterpret_cast<RzConfigNode *>(ptr);
|
||||
CutterRzListForeach (core_a->config->nodes, iter, RzConfigNode, node) {
|
||||
if (!strcmp(node->name, "scr.color") || !strcmp(node->name, "scr.interactive")
|
||||
|| !strcmp(node->name, "cfg.debug")) {
|
||||
rz_config_set(core_b->config, node->name, "0");
|
||||
@ -4614,8 +4610,14 @@ RzAnalysisMatchResult *CutterCore::diffNewFile(const QString &filePath,
|
||||
rz_config_set(core_b->config, node->name, node->value);
|
||||
}
|
||||
|
||||
if (!rz_core_analysis_everything(core_b, false, nullptr)) {
|
||||
qWarning() << "cannot analyze binary " << filePath;
|
||||
if (!rz_core_analysis_all(core_b)) {
|
||||
qWarning() << "cannot perform basic analysis of the binary " << filePath;
|
||||
goto fail;
|
||||
}
|
||||
|
||||
if (level != AnalysisLevelSymbols
|
||||
&& !rz_core_analysis_everything(core_b, level == AnalysisLevelExperimental, nullptr)) {
|
||||
qWarning() << "cannot perform complete analysis of the binary " << filePath;
|
||||
goto fail;
|
||||
}
|
||||
|
||||
@ -4651,10 +4653,10 @@ RzAnalysisMatchResult *CutterCore::diffNewFile(const QString &filePath,
|
||||
return result;
|
||||
|
||||
fail:
|
||||
|
||||
rz_list_free(fcns_a);
|
||||
rz_list_free(fcns_b);
|
||||
rz_core_free(this->core_b);
|
||||
this->core_b = nullptr;
|
||||
rz_core_file_close_all_but(core_b);
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
|
@ -72,7 +72,6 @@ class CUTTER_EXPORT CutterCore : public QObject
|
||||
friend class RzCoreLocked;
|
||||
friend class RizinTask;
|
||||
friend class Basefind;
|
||||
friend class BinDiff;
|
||||
|
||||
public:
|
||||
explicit CutterCore(QObject *parent = nullptr);
|
||||
@ -757,7 +756,13 @@ public:
|
||||
void writeGraphvizGraphToFile(QString path, QString format, RzCoreGraphType type, RVA address);
|
||||
|
||||
/* Diffing/Matching */
|
||||
RzAnalysisMatchResult *diffNewFile(const QString &filePath,
|
||||
enum {
|
||||
AnalysisLevelSymbols = 0,
|
||||
AnalysisLevelComplete,
|
||||
AnalysisLevelExperimental,
|
||||
};
|
||||
|
||||
RzAnalysisMatchResult *diffNewFile(const QString &filePath, int level,
|
||||
RzAnalysisMatchThreadInfoCb callback, void *user);
|
||||
|
||||
signals:
|
||||
|
@ -413,6 +413,13 @@ struct BinDiffMatchDescription
|
||||
double similarity;
|
||||
};
|
||||
|
||||
struct BinDiffStatusDescription
|
||||
{
|
||||
size_t total;
|
||||
size_t nLeft;
|
||||
size_t nMatch;
|
||||
};
|
||||
|
||||
Q_DECLARE_METATYPE(FunctionDescription)
|
||||
Q_DECLARE_METATYPE(ImportDescription)
|
||||
Q_DECLARE_METATYPE(ExportDescription)
|
||||
@ -455,5 +462,6 @@ Q_DECLARE_METATYPE(VariableDescription)
|
||||
Q_DECLARE_METATYPE(BasefindCoreStatusDescription)
|
||||
Q_DECLARE_METATYPE(BasefindResultDescription)
|
||||
Q_DECLARE_METATYPE(BinDiffMatchDescription)
|
||||
Q_DECLARE_METATYPE(BinDiffStatusDescription)
|
||||
|
||||
#endif // DESCRIPTIONS_H
|
||||
|
@ -119,7 +119,7 @@
|
||||
|
||||
// Tools
|
||||
#include "tools/basefind/BaseFindDialog.h"
|
||||
#include "tools/bindiff/DiffLoadDialog.h"
|
||||
#include "tools/bindiff/DiffWaitDialog.h"
|
||||
|
||||
#define PROJECT_FILE_FILTER tr("Rizin Project (*.rzdb)")
|
||||
|
||||
@ -1617,8 +1617,29 @@ void MainWindow::on_actionBackward_triggered()
|
||||
|
||||
void MainWindow::on_actionDiff_triggered()
|
||||
{
|
||||
auto dialog = new DiffLoadDialog(this);
|
||||
dialog->show();
|
||||
if (diffLoadDialog) {
|
||||
delete diffLoadDialog;
|
||||
}
|
||||
diffLoadDialog = new DiffLoadDialog(this);
|
||||
diffLoadDialog->show();
|
||||
connect(diffLoadDialog, &DiffLoadDialog::startDiffing, this, &MainWindow::startDiffing);
|
||||
}
|
||||
|
||||
void MainWindow::startDiffing()
|
||||
{
|
||||
if (!diffLoadDialog) {
|
||||
return;
|
||||
}
|
||||
|
||||
QString modified = diffLoadDialog->getFileToOpen();
|
||||
if (modified.isEmpty()) {
|
||||
messageBoxWarning(tr("Error"), tr("The compare file was not selected."));
|
||||
return;
|
||||
}
|
||||
|
||||
auto level = diffLoadDialog->getLevel();
|
||||
auto diffWait = new DiffWaitDialog(this);
|
||||
diffWait->show(filename, modified, level);
|
||||
}
|
||||
|
||||
void MainWindow::on_actionForward_triggered()
|
||||
|
@ -4,12 +4,12 @@
|
||||
#include "core/Cutter.h" // only needed for ut64
|
||||
#include "dialogs/NewFileDialog.h"
|
||||
#include "dialogs/WelcomeDialog.h"
|
||||
#include "dialogs/bindiff/BinDiffDialog.h"
|
||||
#include "common/Configuration.h"
|
||||
#include "common/InitialOptions.h"
|
||||
#include "common/IOModesController.h"
|
||||
#include "common/CutterLayout.h"
|
||||
#include "MemoryDockWidget.h"
|
||||
#include "tools/bindiff/DiffLoadDialog.h"
|
||||
|
||||
#include <memory>
|
||||
|
||||
@ -164,6 +164,7 @@ private slots:
|
||||
void addExtraHexdump();
|
||||
void addExtraDisassembly();
|
||||
void addExtraDecompiler();
|
||||
void startDiffing();
|
||||
|
||||
void on_actionRefresh_Panels_triggered();
|
||||
|
||||
@ -271,6 +272,7 @@ private:
|
||||
CallGraphWidget *callGraphDock = nullptr;
|
||||
CallGraphWidget *globalCallGraphDock = nullptr;
|
||||
CutterDockWidget *heapDock = nullptr;
|
||||
DiffLoadDialog *diffLoadDialog = nullptr;
|
||||
|
||||
QMenu *disassemblyContextMenuExtensions = nullptr;
|
||||
QMenu *addressableContextMenuExtensions = nullptr;
|
||||
@ -335,7 +337,7 @@ private:
|
||||
|
||||
QSharedPointer<RizinTask> task;
|
||||
RizinTaskDialog *taskDialog = nullptr;
|
||||
BinDiffDialog *binDiffDialog = nullptr;
|
||||
DiffLoadDialog *binDiffDialog = nullptr;
|
||||
};
|
||||
|
||||
#endif // MAINWINDOW_H
|
||||
|
@ -1,137 +0,0 @@
|
||||
#include "core/Cutter.h"
|
||||
#include "BinDiffDialog.h"
|
||||
|
||||
#include "ui_BinDiffDialog.h"
|
||||
#include "common/Configuration.h"
|
||||
#include "common/BugReporting.h"
|
||||
|
||||
#include <QUrl>
|
||||
#include <QTimer>
|
||||
#include <QEventLoop>
|
||||
#include <QJsonObject>
|
||||
#include <QProgressBar>
|
||||
#include <QProgressDialog>
|
||||
#include <UpdateWorker.h>
|
||||
#include <QtNetwork/QNetworkRequest>
|
||||
#include <QtNetwork/QNetworkAccessManager>
|
||||
|
||||
#include "CutterConfig.h"
|
||||
|
||||
typedef struct {
|
||||
QColor perfect;
|
||||
QColor partial;
|
||||
QColor none;
|
||||
} DiffColors;
|
||||
|
||||
inline QString doubleToString(double number)
|
||||
{
|
||||
return QString::asprintf("%.6f", number);
|
||||
}
|
||||
|
||||
inline QTableWidgetItem *newColoredCell(QString text, double similarity, const DiffColors *colors) {
|
||||
auto item = new QTableWidgetItem(text);
|
||||
if (similarity >= 1.0) {
|
||||
item->setBackground(colors->perfect);
|
||||
} else if (similarity >= RZ_ANALYSIS_SIMILARITY_THRESHOLD) {
|
||||
item->setBackground(colors->partial);
|
||||
} else {
|
||||
item->setBackground(colors->none);
|
||||
}
|
||||
item->setForeground(Qt::black);
|
||||
return item;
|
||||
}
|
||||
|
||||
BinDiffDialog::BinDiffDialog(RzAnalysisMatchResult *result, QWidget *parent) : QDialog(parent), ui(new Ui::BinDiffDialog)
|
||||
{
|
||||
ui->setupUi(this);
|
||||
setWindowFlags(windowFlags() & (~Qt::WindowContextHelpButtonHint));
|
||||
|
||||
void *ptr;
|
||||
RzListIter *iter = nullptr;
|
||||
RzAnalysisMatchPair *pair = nullptr;
|
||||
const RzAnalysisFunction *fcn_a = nullptr, *fcn_b = nullptr;
|
||||
|
||||
const DiffColors colors = {
|
||||
.perfect = Config()->getColor("gui.match.perfect"),
|
||||
.partial = Config()->getColor("gui.match.partial"),
|
||||
.none = Config()->getColor("gui.match.none"),
|
||||
};
|
||||
|
||||
size_t n_raws = rz_list_length(result->matches);
|
||||
n_raws += rz_list_length(result->unmatch_a);
|
||||
n_raws += rz_list_length(result->unmatch_b);
|
||||
|
||||
QStringList tableHeader = {
|
||||
tr("name"), tr("size"), tr("addr"),
|
||||
tr("type"), tr("similarity"),
|
||||
tr("addr"), tr("size"), tr("name")
|
||||
};
|
||||
|
||||
ui->resultTable->setRowCount(n_raws);
|
||||
ui->resultTable->setColumnCount(8);
|
||||
ui->resultTable->setHorizontalHeaderLabels(tableHeader);
|
||||
ui->resultTable->verticalHeader()->setVisible(false);
|
||||
ui->resultTable->horizontalHeader()->setSectionResizeMode(QHeaderView::Stretch);
|
||||
|
||||
n_raws = 0;
|
||||
rz_list_foreach(result->matches, iter, ptr) {
|
||||
pair = static_cast<RzAnalysisMatchPair *>(ptr);
|
||||
fcn_a = static_cast<const RzAnalysisFunction *>(pair->pair_a);
|
||||
fcn_b = static_cast<const RzAnalysisFunction *>(pair->pair_b);
|
||||
|
||||
QString size_a = RzSizeString(rz_analysis_function_realsize(fcn_a));
|
||||
QString size_b = RzSizeString(rz_analysis_function_realsize(fcn_b));
|
||||
QString addr_a = RzAddressString(fcn_a->addr);
|
||||
QString addr_b = RzAddressString(fcn_b->addr);
|
||||
QString simtype = RZ_ANALYSIS_SIMILARITY_TYPE_STR(pair->similarity);
|
||||
QString similarity = doubleToString(pair->similarity);
|
||||
|
||||
ui->resultTable->setItem(n_raws, ColumnSourceName, newColoredCell(fcn_a->name, pair->similarity, &colors));
|
||||
ui->resultTable->setItem(n_raws, ColumnSourceSize, newColoredCell(size_a, pair->similarity, &colors));
|
||||
ui->resultTable->setItem(n_raws, ColumnSourceAddr, newColoredCell(addr_a, pair->similarity, &colors));
|
||||
ui->resultTable->setItem(n_raws, ColumnSimilarityType, newColoredCell(simtype, pair->similarity, &colors));
|
||||
ui->resultTable->setItem(n_raws, ColumnSimilarityNum, newColoredCell(similarity, pair->similarity, &colors));
|
||||
ui->resultTable->setItem(n_raws, ColumnMatchAddr, newColoredCell(addr_b, pair->similarity, &colors));
|
||||
ui->resultTable->setItem(n_raws, ColumnMatchSize, newColoredCell(size_b, pair->similarity, &colors));
|
||||
ui->resultTable->setItem(n_raws, ColumnMatchName, newColoredCell(fcn_b->name, pair->similarity, &colors));
|
||||
n_raws++;
|
||||
}
|
||||
|
||||
rz_list_foreach(result->unmatch_a, iter, ptr) {
|
||||
fcn_a = static_cast<RzAnalysisFunction *>(ptr);
|
||||
QString size_a = RzSizeString(rz_analysis_function_realsize(fcn_a));
|
||||
QString addr_a = RzAddressString(fcn_a->addr);
|
||||
ui->resultTable->setItem(n_raws, ColumnSourceName, newColoredCell(fcn_a->name, 0.0, &colors));
|
||||
ui->resultTable->setItem(n_raws, ColumnSourceSize, newColoredCell(size_a, 0.0, &colors));
|
||||
ui->resultTable->setItem(n_raws, ColumnSourceAddr, newColoredCell(addr_a, 0.0, &colors));
|
||||
ui->resultTable->setItem(n_raws, ColumnSimilarityType, newColoredCell(RZ_ANALYSIS_SIMILARITY_UNLIKE_STR, 0.0, &colors));
|
||||
ui->resultTable->setItem(n_raws, ColumnSimilarityNum, newColoredCell("0.000000", 0.0, &colors));
|
||||
ui->resultTable->setItem(n_raws, ColumnMatchAddr, newColoredCell("------", 0.0, &colors));
|
||||
ui->resultTable->setItem(n_raws, ColumnMatchSize, newColoredCell("------", 0.0, &colors));
|
||||
ui->resultTable->setItem(n_raws, ColumnMatchName, newColoredCell("------", 0.0, &colors));
|
||||
n_raws++;
|
||||
}
|
||||
|
||||
rz_list_foreach(result->unmatch_b, iter, ptr) {
|
||||
fcn_b = static_cast<RzAnalysisFunction *>(ptr);
|
||||
QString size_b = RzSizeString(rz_analysis_function_realsize(fcn_b));
|
||||
QString addr_b = RzAddressString(fcn_b->addr);
|
||||
ui->resultTable->setItem(n_raws, ColumnSourceName, newColoredCell("------", 0.0, &colors));
|
||||
ui->resultTable->setItem(n_raws, ColumnSourceSize, newColoredCell("------", 0.0, &colors));
|
||||
ui->resultTable->setItem(n_raws, ColumnSourceAddr, newColoredCell("------", 0.0, &colors));
|
||||
ui->resultTable->setItem(n_raws, ColumnSimilarityType, newColoredCell(RZ_ANALYSIS_SIMILARITY_UNLIKE_STR, 0.0, &colors));
|
||||
ui->resultTable->setItem(n_raws, ColumnSimilarityNum, newColoredCell("0.000000", 0.0, &colors));
|
||||
ui->resultTable->setItem(n_raws, ColumnMatchAddr, newColoredCell(fcn_b->name, 0.0, &colors));
|
||||
ui->resultTable->setItem(n_raws, ColumnMatchSize, newColoredCell(size_b, 0.0, &colors));
|
||||
ui->resultTable->setItem(n_raws, ColumnMatchName, newColoredCell(addr_b, 0.0, &colors));
|
||||
n_raws++;
|
||||
}
|
||||
}
|
||||
|
||||
BinDiffDialog::~BinDiffDialog() {}
|
||||
|
||||
void BinDiffDialog::on_buttonBox_rejected()
|
||||
{
|
||||
close();
|
||||
}
|
||||
|
@ -1,37 +0,0 @@
|
||||
#ifndef BINDIFFDIALOG_H
|
||||
#define BINDIFFDIALOG_H
|
||||
|
||||
#include <QDialog>
|
||||
#include <memory>
|
||||
#include <QtNetwork/QNetworkReply>
|
||||
|
||||
namespace Ui {
|
||||
class BinDiffDialog;
|
||||
}
|
||||
|
||||
class BinDiffDialog : public QDialog
|
||||
{
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
explicit BinDiffDialog(RzAnalysisMatchResult *result, QWidget *parent = nullptr);
|
||||
~BinDiffDialog();
|
||||
|
||||
private slots:
|
||||
void on_buttonBox_rejected();
|
||||
|
||||
private:
|
||||
enum {
|
||||
ColumnSourceName = 0,
|
||||
ColumnSourceSize,
|
||||
ColumnSourceAddr,
|
||||
ColumnSimilarityType,
|
||||
ColumnSimilarityNum,
|
||||
ColumnMatchAddr,
|
||||
ColumnMatchSize,
|
||||
ColumnMatchName
|
||||
} BinDiffTableColumn;
|
||||
std::unique_ptr<Ui::BinDiffDialog> ui;
|
||||
};
|
||||
|
||||
#endif // BINDIFFDIALOG_H
|
@ -1,55 +0,0 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<ui version="4.0">
|
||||
<class>BinDiffDialog</class>
|
||||
<widget class="QDialog" name="BinDiffDialog">
|
||||
<property name="geometry">
|
||||
<rect>
|
||||
<x>0</x>
|
||||
<y>0</y>
|
||||
<width>935</width>
|
||||
<height>554</height>
|
||||
</rect>
|
||||
</property>
|
||||
<property name="windowTitle">
|
||||
<string>Cutter Binary Diffing Tool</string>
|
||||
</property>
|
||||
<layout class="QVBoxLayout" name="verticalLayout">
|
||||
<item>
|
||||
<widget class="QMenuBar" name="menuBar">
|
||||
<property name="geometry">
|
||||
<rect>
|
||||
<x>0</x>
|
||||
<y>0</y>
|
||||
<width>1013</width>
|
||||
<height>22</height>
|
||||
</rect>
|
||||
</property>
|
||||
<property name="defaultUp">
|
||||
<bool>false</bool>
|
||||
</property>
|
||||
<property name="nativeMenuBar">
|
||||
<bool>true</bool>
|
||||
</property>
|
||||
<widget class="QMenu" name="menuExport">
|
||||
<property name="title">
|
||||
<string>Export</string>
|
||||
</property>
|
||||
</widget>
|
||||
<addaction name="menuExport"/>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QTableWidget" name="resultTable"/>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QDialogButtonBox" name="buttonBox">
|
||||
<property name="standardButtons">
|
||||
<set>QDialogButtonBox::Close</set>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
<resources/>
|
||||
<connections/>
|
||||
</ui>
|
@ -16,7 +16,7 @@ BaseFindDialog::BaseFindDialog(QWidget *parent) : QDialog(parent), ui(new Ui::Ba
|
||||
ui->nCoresCombo->clear();
|
||||
for (size_t i = n_cores; i > 0; i--) {
|
||||
if (n_cores == i) {
|
||||
ui->nCoresCombo->addItem("All Cores");
|
||||
ui->nCoresCombo->addItem(tr("All CPU Cores"));
|
||||
continue;
|
||||
}
|
||||
ui->nCoresCombo->addItem(QString::number(i));
|
||||
|
@ -1,6 +1,8 @@
|
||||
#include "DiffLoadDialog.h"
|
||||
#include "ui_DiffLoadDialog.h"
|
||||
|
||||
#include "DiffWaitDialog.h"
|
||||
|
||||
#include <core/Cutter.h>
|
||||
#include <rz_th.h>
|
||||
|
||||
@ -17,6 +19,13 @@ DiffLoadDialog::DiffLoadDialog(QWidget *parent) : QDialog(parent), ui(new Ui::Di
|
||||
|
||||
ui->lineEditDiffFile->setReadOnly(true);
|
||||
ui->lineEditDiffFile->setText("");
|
||||
|
||||
ui->comboBoxAnalysis->addItem(tr("Basic"));
|
||||
ui->comboBoxAnalysis->addItem(tr("Auto"));
|
||||
ui->comboBoxAnalysis->addItem(tr("Experimental"));
|
||||
|
||||
auto index = ui->comboBoxAnalysis->findData(tr("Auto"), Qt::DisplayRole);
|
||||
ui->comboBoxAnalysis->setCurrentIndex(index);
|
||||
}
|
||||
|
||||
DiffLoadDialog::~DiffLoadDialog() {}
|
||||
@ -31,6 +40,11 @@ QString DiffLoadDialog::getPreviousDiffFile() const
|
||||
return ui->lineEditDiffFile->text();
|
||||
}
|
||||
|
||||
int DiffLoadDialog::getLevel() const
|
||||
{
|
||||
return ui->comboBoxAnalysis->currentIndex();
|
||||
}
|
||||
|
||||
void DiffLoadDialog::on_buttonDiffOpen_clicked()
|
||||
{
|
||||
QFileDialog dialog(this);
|
||||
@ -69,26 +83,9 @@ void DiffLoadDialog::on_buttonFileOpen_clicked()
|
||||
ui->lineEditFileName->setText(fileName);
|
||||
}
|
||||
|
||||
void DiffLoadDialog::openErrorBox(QString errorMessage)
|
||||
{
|
||||
QMessageBox mb(this);
|
||||
mb.setIcon(QMessageBox::Warning);
|
||||
mb.setStandardButtons(QMessageBox::Ok);
|
||||
mb.setWindowTitle(tr("Error"));
|
||||
mb.setText(errorMessage);
|
||||
mb.exec();
|
||||
}
|
||||
|
||||
void DiffLoadDialog::on_buttonBox_accepted()
|
||||
{
|
||||
QString fileName = getFileToOpen();
|
||||
if (fileName.isEmpty()) {
|
||||
openErrorBox(tr("The compare file was not selected."));
|
||||
return;
|
||||
}
|
||||
emit startDiffing();
|
||||
}
|
||||
|
||||
void DiffLoadDialog::on_buttonBox_rejected()
|
||||
{
|
||||
// cancel
|
||||
}
|
||||
void DiffLoadDialog::on_buttonBox_rejected() {}
|
||||
|
@ -21,6 +21,10 @@ public:
|
||||
|
||||
QString getFileToOpen() const;
|
||||
QString getPreviousDiffFile() const;
|
||||
int getLevel() const;
|
||||
|
||||
signals:
|
||||
void startDiffing();
|
||||
|
||||
private slots:
|
||||
void on_buttonDiffOpen_clicked();
|
||||
@ -30,8 +34,6 @@ private slots:
|
||||
|
||||
private:
|
||||
std::unique_ptr<Ui::DiffLoadDialog> ui;
|
||||
|
||||
void openErrorBox(QString errorMessage);
|
||||
};
|
||||
|
||||
#endif // DIFF_LOAD_DIALOG_H
|
||||
|
@ -10,7 +10,7 @@
|
||||
<x>0</x>
|
||||
<y>0</y>
|
||||
<width>636</width>
|
||||
<height>142</height>
|
||||
<height>184</height>
|
||||
</rect>
|
||||
</property>
|
||||
<property name="sizePolicy">
|
||||
@ -34,9 +34,6 @@
|
||||
<item row="1" column="1">
|
||||
<widget class="QLineEdit" name="lineEditDiffFile"/>
|
||||
</item>
|
||||
<item row="0" column="1">
|
||||
<widget class="QLineEdit" name="lineEditFileName"/>
|
||||
</item>
|
||||
<item row="0" column="0">
|
||||
<widget class="QLabel" name="fileToCompareLabel">
|
||||
<property name="sizePolicy">
|
||||
@ -53,13 +50,6 @@
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="1" column="2">
|
||||
<widget class="QPushButton" name="buttonDiffOpen">
|
||||
<property name="text">
|
||||
<string>Select</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="0" column="2">
|
||||
<widget class="QPushButton" name="buttonFileOpen">
|
||||
<property name="text">
|
||||
@ -83,6 +73,26 @@
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="0" column="1">
|
||||
<widget class="QLineEdit" name="lineEditFileName"/>
|
||||
</item>
|
||||
<item row="1" column="2">
|
||||
<widget class="QPushButton" name="buttonDiffOpen">
|
||||
<property name="text">
|
||||
<string>Select</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="2" column="0">
|
||||
<widget class="QLabel" name="labelAnalysisLevel">
|
||||
<property name="text">
|
||||
<string>Analysis Level</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="2" column="1">
|
||||
<widget class="QComboBox" name="comboBoxAnalysis"/>
|
||||
</item>
|
||||
</layout>
|
||||
</item>
|
||||
<item>
|
||||
|
106
src/tools/bindiff/DiffWaitDialog.cpp
Normal file
106
src/tools/bindiff/DiffWaitDialog.cpp
Normal file
@ -0,0 +1,106 @@
|
||||
#include "DiffWaitDialog.h"
|
||||
#include "ui_DiffWaitDialog.h"
|
||||
|
||||
#include <QTime>
|
||||
|
||||
#include <core/Cutter.h>
|
||||
#include <rz_util.h>
|
||||
|
||||
DiffWaitDialog::DiffWaitDialog(QWidget *parent)
|
||||
: QDialog(parent), timer(parent), bDiff(new BinDiff()), ui(new Ui::DiffWaitDialog)
|
||||
{
|
||||
ui->setupUi(this);
|
||||
setWindowFlags(windowFlags() & (~Qt::WindowContextHelpButtonHint));
|
||||
|
||||
ui->lineEditNFuncs->setReadOnly(true);
|
||||
ui->lineEditMatches->setReadOnly(true);
|
||||
ui->lineEditEstimatedTime->setReadOnly(true);
|
||||
ui->lineEditElapsedTime->setReadOnly(true);
|
||||
ui->lineEditOriginal->setReadOnly(true);
|
||||
ui->lineEditModified->setReadOnly(true);
|
||||
ui->progressBar->setValue(0);
|
||||
ui->lineEditNFuncs->setText("0");
|
||||
ui->lineEditMatches->setText("0");
|
||||
|
||||
QTime zero(0, 0, 0, 0);
|
||||
ui->lineEditElapsedTime->setText(zero.toString("hh:mm:ss"));
|
||||
ui->lineEditEstimatedTime->setText(zero.toString("hh:mm:ss"));
|
||||
}
|
||||
|
||||
DiffWaitDialog::~DiffWaitDialog()
|
||||
{
|
||||
if (bDiff->isRunning()) {
|
||||
bDiff->cancel();
|
||||
bDiff->wait();
|
||||
}
|
||||
}
|
||||
|
||||
QList<BinDiffMatchDescription> DiffWaitDialog::matches()
|
||||
{
|
||||
return bDiff->matches();
|
||||
}
|
||||
|
||||
QList<FunctionDescription> DiffWaitDialog::mismatch(bool fileA)
|
||||
{
|
||||
return bDiff->mismatch(fileA);
|
||||
}
|
||||
|
||||
void DiffWaitDialog::show(QString original, QString modified, int level)
|
||||
{
|
||||
connect(this, &DiffWaitDialog::cancelJob, bDiff.get(), &BinDiff::cancel);
|
||||
connect(bDiff.get(), &BinDiff::progress, this, &DiffWaitDialog::onProgress);
|
||||
connect(bDiff.get(), &BinDiff::complete, this, &DiffWaitDialog::onCompletion);
|
||||
connect(&timer, &QTimer::timeout, this, &DiffWaitDialog::updateElapsedTime);
|
||||
|
||||
ui->lineEditOriginal->setText(original);
|
||||
ui->lineEditModified->setText(modified);
|
||||
|
||||
bDiff->setAnalysisLevel(level);
|
||||
bDiff->setFile(modified);
|
||||
eTimer.restart();
|
||||
timer.setSingleShot(false);
|
||||
timer.start(1000);
|
||||
|
||||
bDiff->start();
|
||||
this->QDialog::show();
|
||||
}
|
||||
|
||||
void DiffWaitDialog::onProgress(BinDiffStatusDescription status)
|
||||
{
|
||||
int partial = status.total - status.nLeft;
|
||||
ut32 progress = (100 * partial) / status.total;
|
||||
ui->progressBar->setValue(progress);
|
||||
ui->lineEditNFuncs->setText(QString::asprintf("%lu", status.nLeft));
|
||||
ui->lineEditMatches->setText(QString::asprintf("%lu", status.nMatch));
|
||||
|
||||
double speed = ((double)partial) / ((double)eTimer.elapsed());
|
||||
ut64 seconds = (((double)status.nLeft) / speed) / 1000ull;
|
||||
int hours = seconds / 3600;
|
||||
seconds -= (hours * 3600);
|
||||
int minutes = seconds / 60;
|
||||
seconds = seconds % 60;
|
||||
QTime estimated(hours, minutes, seconds, 0);
|
||||
ui->lineEditEstimatedTime->setText(estimated.toString("hh:mm:ss"));
|
||||
}
|
||||
|
||||
void DiffWaitDialog::onCompletion()
|
||||
{
|
||||
timer.stop();
|
||||
}
|
||||
|
||||
void DiffWaitDialog::updateElapsedTime()
|
||||
{
|
||||
ut64 seconds = eTimer.elapsed() / 1000ull;
|
||||
int hours = seconds / 3600;
|
||||
seconds -= (hours * 3600);
|
||||
int minutes = seconds / 60;
|
||||
seconds = seconds % 60;
|
||||
QTime current(hours, minutes, seconds, 0);
|
||||
ui->lineEditElapsedTime->setText(current.toString("hh:mm:ss"));
|
||||
}
|
||||
|
||||
void DiffWaitDialog::on_buttonBox_rejected()
|
||||
{
|
||||
timer.stop();
|
||||
emit cancelJob();
|
||||
}
|
48
src/tools/bindiff/DiffWaitDialog.h
Normal file
48
src/tools/bindiff/DiffWaitDialog.h
Normal file
@ -0,0 +1,48 @@
|
||||
#ifndef DIFF_WAIT_DIALOG_H
|
||||
#define DIFF_WAIT_DIALOG_H
|
||||
|
||||
#include <QDialog>
|
||||
#include <QListWidgetItem>
|
||||
#include <QProgressBar>
|
||||
#include <QTimer>
|
||||
#include <QElapsedTimer>
|
||||
#include <memory>
|
||||
|
||||
#include <core/Cutter.h>
|
||||
|
||||
namespace Ui {
|
||||
class DiffWaitDialog;
|
||||
}
|
||||
|
||||
class DiffWaitDialog : public QDialog
|
||||
{
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
explicit DiffWaitDialog(QWidget *parent = nullptr);
|
||||
~DiffWaitDialog();
|
||||
|
||||
void show(QString original, QString modified, int level);
|
||||
|
||||
QList<BinDiffMatchDescription> matches();
|
||||
QList<FunctionDescription> mismatch(bool fileA);
|
||||
|
||||
public slots:
|
||||
void onProgress(BinDiffStatusDescription status);
|
||||
void onCompletion();
|
||||
void updateElapsedTime();
|
||||
|
||||
signals:
|
||||
void cancelJob();
|
||||
|
||||
private slots:
|
||||
void on_buttonBox_rejected();
|
||||
|
||||
private:
|
||||
QElapsedTimer eTimer;
|
||||
QTimer timer;
|
||||
std::unique_ptr<BinDiff> bDiff;
|
||||
std::unique_ptr<Ui::DiffWaitDialog> ui;
|
||||
};
|
||||
|
||||
#endif // DIFF_WAIT_DIALOG_H
|
151
src/tools/bindiff/DiffWaitDialog.ui
Normal file
151
src/tools/bindiff/DiffWaitDialog.ui
Normal file
@ -0,0 +1,151 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<ui version="4.0">
|
||||
<class>DiffWaitDialog</class>
|
||||
<widget class="QDialog" name="DiffWaitDialog">
|
||||
<property name="windowModality">
|
||||
<enum>Qt::NonModal</enum>
|
||||
</property>
|
||||
<property name="geometry">
|
||||
<rect>
|
||||
<x>0</x>
|
||||
<y>0</y>
|
||||
<width>524</width>
|
||||
<height>342</height>
|
||||
</rect>
|
||||
</property>
|
||||
<property name="sizePolicy">
|
||||
<sizepolicy hsizetype="Minimum" vsizetype="Minimum">
|
||||
<horstretch>0</horstretch>
|
||||
<verstretch>0</verstretch>
|
||||
</sizepolicy>
|
||||
</property>
|
||||
<property name="windowTitle">
|
||||
<string notr="true">Performing binary diffing</string>
|
||||
</property>
|
||||
<layout class="QVBoxLayout" name="verticalLayout_2">
|
||||
<property name="sizeConstraint">
|
||||
<enum>QLayout::SetMinimumSize</enum>
|
||||
</property>
|
||||
<item>
|
||||
<layout class="QVBoxLayout" name="mainVerticalLayout">
|
||||
<property name="sizeConstraint">
|
||||
<enum>QLayout::SetMinimumSize</enum>
|
||||
</property>
|
||||
<item>
|
||||
<widget class="QProgressBar" name="progressBar">
|
||||
<property name="value">
|
||||
<number>24</number>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<layout class="QGridLayout" name="gridLayout">
|
||||
<item row="3" column="1">
|
||||
<widget class="QLineEdit" name="lineEditElapsedTime"/>
|
||||
</item>
|
||||
<item row="1" column="1">
|
||||
<widget class="QLineEdit" name="lineEditModified"/>
|
||||
</item>
|
||||
<item row="3" column="0">
|
||||
<widget class="QLabel" name="labelElapsedTime">
|
||||
<property name="text">
|
||||
<string>Elapsed Time</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="1" column="0">
|
||||
<widget class="QLabel" name="labelModified">
|
||||
<property name="text">
|
||||
<string>Modified File</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="5" column="0">
|
||||
<widget class="QLabel" name="labelMatches">
|
||||
<property name="text">
|
||||
<string>Matches</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="0" column="1">
|
||||
<widget class="QLineEdit" name="lineEditOriginal"/>
|
||||
</item>
|
||||
<item row="0" column="0">
|
||||
<widget class="QLabel" name="labelOrignal">
|
||||
<property name="text">
|
||||
<string>Original File</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="4" column="1">
|
||||
<widget class="QLineEdit" name="lineEditNFuncs"/>
|
||||
</item>
|
||||
<item row="4" column="0">
|
||||
<widget class="QLabel" name="labelNFuncs">
|
||||
<property name="text">
|
||||
<string>Functions left to compare</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="5" column="1">
|
||||
<widget class="QLineEdit" name="lineEditMatches"/>
|
||||
</item>
|
||||
<item row="2" column="0">
|
||||
<widget class="QLabel" name="labelEstimatedTime">
|
||||
<property name="text">
|
||||
<string>Estimated Time</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="2" column="1">
|
||||
<widget class="QLineEdit" name="lineEditEstimatedTime"/>
|
||||
</item>
|
||||
</layout>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QDialogButtonBox" name="buttonBox">
|
||||
<property name="orientation">
|
||||
<enum>Qt::Horizontal</enum>
|
||||
</property>
|
||||
<property name="standardButtons">
|
||||
<set>QDialogButtonBox::Cancel</set>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</item>
|
||||
</layout>
|
||||
<action name="actionRemoveItem">
|
||||
<property name="text">
|
||||
<string>Remove item</string>
|
||||
</property>
|
||||
</action>
|
||||
<action name="actionRemoveAll">
|
||||
<property name="text">
|
||||
<string>Remove all</string>
|
||||
</property>
|
||||
<property name="toolTip">
|
||||
<string>Remove all</string>
|
||||
</property>
|
||||
</action>
|
||||
</widget>
|
||||
<resources/>
|
||||
<connections>
|
||||
<connection>
|
||||
<sender>buttonBox</sender>
|
||||
<signal>rejected()</signal>
|
||||
<receiver>DiffWaitDialog</receiver>
|
||||
<slot>reject()</slot>
|
||||
<hints>
|
||||
<hint type="sourcelabel">
|
||||
<x>316</x>
|
||||
<y>240</y>
|
||||
</hint>
|
||||
<hint type="destinationlabel">
|
||||
<x>286</x>
|
||||
<y>254</y>
|
||||
</hint>
|
||||
</hints>
|
||||
</connection>
|
||||
</connections>
|
||||
</ui>
|
Loading…
Reference in New Issue
Block a user