Initial working diff with resizable columns

This commit is contained in:
wargio 2024-01-02 21:43:49 +08:00
parent d974c24daa
commit 0a5a1dfbcf
16 changed files with 258 additions and 70 deletions

View File

@ -22,6 +22,11 @@ BinDiff::~BinDiff()
rz_analysis_match_result_free(result); rz_analysis_match_result_free(result);
} }
bool BinDiff::hasData()
{
return result != nullptr;
}
void BinDiff::setFile(QString filePath) void BinDiff::setFile(QString filePath)
{ {
mutex.lock(); mutex.lock();
@ -36,6 +41,13 @@ void BinDiff::setAnalysisLevel(int aLevel)
mutex.unlock(); mutex.unlock();
} }
void BinDiff::setCompareLogic(int cLogic)
{
mutex.lock();
compareLogic = cLogic;
mutex.unlock();
}
void BinDiff::run() void BinDiff::run()
{ {
qRegisterMetaType<BinDiffStatusDescription>(); qRegisterMetaType<BinDiffStatusDescription>();
@ -47,7 +59,7 @@ void BinDiff::run()
maxTotal = 1; // maxTotal must be at least 1. maxTotal = 1; // maxTotal must be at least 1.
mutex.unlock(); mutex.unlock();
result = Core()->diffNewFile(file, level, threadCallback, this); result = Core()->diffNewFile(file, level, compareLogic, threadCallback, this);
mutex.lock(); mutex.lock();
bool canComplete = continueRun; bool canComplete = continueRun;

View File

@ -20,6 +20,8 @@ public:
void setFile(QString filePth); void setFile(QString filePth);
void setAnalysisLevel(int aLevel); void setAnalysisLevel(int aLevel);
void setCompareLogic(int cLogic);
bool hasData();
QList<BinDiffMatchDescription> matches(); QList<BinDiffMatchDescription> matches();
QList<FunctionDescription> mismatch(bool originalFile); QList<FunctionDescription> mismatch(bool originalFile);
@ -42,6 +44,7 @@ private:
#endif #endif
QString file; QString file;
int level; int level;
int compareLogic;
bool updateProgress(const size_t nLeft, const size_t nMatch); bool updateProgress(const size_t nLeft, const size_t nMatch);
static bool threadCallback(const size_t nLeft, const size_t nMatch, void *user); static bool threadCallback(const size_t nLeft, const size_t nMatch, void *user);

View File

@ -4564,8 +4564,13 @@ bool CutterCore::isWriteModeEnabled()
return false; return false;
} }
RzList *get_functions(RzAnalysis *analysis) #define IS_IMPORT(name) \
(name.startsWith("sym.imp.") || name.startsWith("loc.imp.") || name.startsWith("imp."))
#define IS_SYMBOL(name, pfx) (IS_IMPORT(name) || name.startsWith(pfx))
RzList *get_functions(RzAnalysis *analysis, int compareLogic)
{ {
RzList *functions = rz_analysis_get_fcns(analysis); RzList *functions = rz_analysis_get_fcns(analysis);
if (!functions) { if (!functions) {
return nullptr; return nullptr;
@ -4576,12 +4581,21 @@ RzList *get_functions(RzAnalysis *analysis)
return list; return list;
} }
QString pfx = Config()->getConfigString("analysis.fcnprefix");
if (pfx.isEmpty()) {
pfx = "fcn.";
} else {
pfx += ".";
}
RzAnalysisFunction *func = nullptr; RzAnalysisFunction *func = nullptr;
RzListIter *it = nullptr; RzListIter *it = nullptr;
CutterRzListForeach (functions, it, RzAnalysisFunction, func) { CutterRzListForeach (functions, it, RzAnalysisFunction, func) {
QString name = func->name; QString name = func->name;
if (name.startsWith("sym.imp.") || name.startsWith("loc.imp.") || name.startsWith("imp.")) { if (compareLogic == CutterCore::CompareLogicDefault && IS_IMPORT(name)) {
continue;
} else if (compareLogic == CutterCore::CompareLogicSymbols && IS_SYMBOL(name, pfx)) {
continue; continue;
} }
rz_list_add_sorted(list, func, analysis->columnSort); rz_list_add_sorted(list, func, analysis->columnSort);
@ -4590,7 +4604,7 @@ RzList *get_functions(RzAnalysis *analysis)
return list; return list;
} }
RzAnalysisMatchResult *CutterCore::diffNewFile(const QString &filePath, int level, RzAnalysisMatchResult *CutterCore::diffNewFile(const QString &filePath, int level, int compareLogic,
RzAnalysisMatchThreadInfoCb callback, void *user) RzAnalysisMatchThreadInfoCb callback, void *user)
{ {
CORE_LOCK(); CORE_LOCK();
@ -4613,17 +4627,17 @@ RzAnalysisMatchResult *CutterCore::diffNewFile(const QString &filePath, int leve
} }
if (!rz_core_file_open(core_b, filePath.toUtf8().constData(), RZ_PERM_RX, 0)) { if (!rz_core_file_open(core_b, filePath.toUtf8().constData(), RZ_PERM_RX, 0)) {
qWarning() << "cannot open file " << filePath; qWarning() << tr("cannot open file %1").arg(filePath);
goto fail; goto fail;
} }
if (!rz_core_bin_load(core_b, nullptr, UT64_MAX)) { if (!rz_core_bin_load(core_b, nullptr, UT64_MAX)) {
qWarning() << "cannot load bin " << filePath; qWarning() << tr("cannot load bin %1").arg(filePath);
goto fail; goto fail;
} }
if (!rz_core_bin_update_arch_bits(core_b)) { if (!rz_core_bin_update_arch_bits(core_b)) {
qWarning() << "cannot set architecture with bits"; qWarning() << tr("cannot set architecture with bits");
goto fail; goto fail;
} }
@ -4637,25 +4651,25 @@ RzAnalysisMatchResult *CutterCore::diffNewFile(const QString &filePath, int leve
} }
if (!rz_core_analysis_all(core_b)) { if (!rz_core_analysis_all(core_b)) {
qWarning() << "cannot perform basic analysis of the binary " << filePath; qWarning() << tr("cannot perform basic analysis of the binary %1").arg(filePath);
goto fail; goto fail;
} }
if (level != AnalysisLevelSymbols if (level != AnalysisLevelSymbols
&& !rz_core_analysis_everything(core_b, level == AnalysisLevelExperimental, nullptr)) { && !rz_core_analysis_everything(core_b, level == AnalysisLevelExperimental, nullptr)) {
qWarning() << "cannot perform complete analysis of the binary " << filePath; qWarning() << tr("cannot perform complete analysis of the binary %1").arg(filePath);
goto fail; goto fail;
} }
fcns_a = get_functions(core_a->analysis); fcns_a = get_functions(core_a->analysis, compareLogic);
if (rz_list_empty(fcns_a)) { if (rz_list_empty(fcns_a)) {
qWarning() << "no functions found in the current opened file"; qWarning() << tr("no functions found in the current opened file");
goto fail; goto fail;
} }
fcns_b = get_functions(core_b->analysis); fcns_b = get_functions(core_b->analysis, compareLogic);
if (rz_list_empty(fcns_b)) { if (rz_list_empty(fcns_b)) {
qWarning() << "no functions found in " << filePath; qWarning() << tr("no functions found in the just opene file %1").arg(filePath);
goto fail; goto fail;
} }
@ -4667,7 +4681,7 @@ RzAnalysisMatchResult *CutterCore::diffNewFile(const QString &filePath, int leve
// calculate all the matches between the functions of the 2 different core files. // calculate all the matches between the functions of the 2 different core files.
result = rz_analysis_match_functions(fcns_a, fcns_b, &opts); result = rz_analysis_match_functions(fcns_a, fcns_b, &opts);
if (!result) { if (!result) {
qWarning() << "failed to perform the function matching operation or job was cancelled."; qWarning() << tr("failed to perform the function matching operation or job was cancelled.");
goto fail; goto fail;
} }

View File

@ -762,7 +762,13 @@ public:
AnalysisLevelExperimental, AnalysisLevelExperimental,
}; };
RzAnalysisMatchResult *diffNewFile(const QString &filePath, int level, enum {
CompareLogicDefault = 0, ///< Only symbols and functions (no imports)
CompareLogicComplete, ///< All functions (imports included)
CompareLogicSymbols, ///< Only symbols
};
RzAnalysisMatchResult *diffNewFile(const QString &filePath, int level, int compareLogic,
RzAnalysisMatchThreadInfoCb callback, void *user); RzAnalysisMatchThreadInfoCb callback, void *user);
signals: signals:

View File

@ -1638,8 +1638,9 @@ void MainWindow::startDiffing()
} }
auto level = diffLoadDialog->getLevel(); auto level = diffLoadDialog->getLevel();
auto compare = diffLoadDialog->getCompare();
auto diffWait = new DiffWaitDialog(this); auto diffWait = new DiffWaitDialog(this);
diffWait->show(filename, modified, level); diffWait->show(filename, modified, level, compare);
} }
void MainWindow::on_actionForward_triggered() void MainWindow::on_actionForward_triggered()

View File

@ -10,6 +10,7 @@ BaseFindDialog::BaseFindDialog(QWidget *parent) : QDialog(parent), ui(new Ui::Ba
{ {
ui->setupUi(this); ui->setupUi(this);
setWindowFlags(windowFlags() & (~Qt::WindowContextHelpButtonHint)); setWindowFlags(windowFlags() & (~Qt::WindowContextHelpButtonHint));
setModal(true);
// Fill in N-thread Combo // Fill in N-thread Combo
size_t n_cores = rz_th_physical_core_number(); size_t n_cores = rz_th_physical_core_number();

View File

@ -72,6 +72,7 @@ BaseFindResultsDialog::BaseFindResultsDialog(QList<BasefindResultDescription> re
{ {
ui->setupUi(this); ui->setupUi(this);
setWindowFlags(windowFlags() & (~Qt::WindowContextHelpButtonHint)); setWindowFlags(windowFlags() & (~Qt::WindowContextHelpButtonHint));
setModal(true);
model = new BaseFindResultsModel(&list, this); model = new BaseFindResultsModel(&list, this);
ui->tableView->setModel(model); ui->tableView->setModel(model);

View File

@ -14,6 +14,7 @@ BaseFindSearchDialog::BaseFindSearchDialog(QWidget *parent)
{ {
ui->setupUi(this); ui->setupUi(this);
setWindowFlags(windowFlags() & (~Qt::WindowContextHelpButtonHint)); setWindowFlags(windowFlags() & (~Qt::WindowContextHelpButtonHint));
setModal(true);
} }
BaseFindSearchDialog::~BaseFindSearchDialog() {} BaseFindSearchDialog::~BaseFindSearchDialog() {}

View File

@ -13,6 +13,7 @@ DiffLoadDialog::DiffLoadDialog(QWidget *parent) : QDialog(parent), ui(new Ui::Di
{ {
ui->setupUi(this); ui->setupUi(this);
setWindowFlags(windowFlags() & (~Qt::WindowContextHelpButtonHint)); setWindowFlags(windowFlags() & (~Qt::WindowContextHelpButtonHint));
setModal(true);
ui->lineEditFileName->setReadOnly(true); ui->lineEditFileName->setReadOnly(true);
ui->lineEditFileName->setText(""); ui->lineEditFileName->setText("");
@ -24,6 +25,10 @@ DiffLoadDialog::DiffLoadDialog(QWidget *parent) : QDialog(parent), ui(new Ui::Di
ui->comboBoxAnalysis->addItem(tr("Auto")); ui->comboBoxAnalysis->addItem(tr("Auto"));
ui->comboBoxAnalysis->addItem(tr("Experimental")); ui->comboBoxAnalysis->addItem(tr("Experimental"));
ui->comboBoxCompare->addItem(tr("Default"));
ui->comboBoxCompare->addItem(tr("All functions"));
ui->comboBoxCompare->addItem(tr("Only Symbols"));
auto index = ui->comboBoxAnalysis->findData(tr("Auto"), Qt::DisplayRole); auto index = ui->comboBoxAnalysis->findData(tr("Auto"), Qt::DisplayRole);
ui->comboBoxAnalysis->setCurrentIndex(index); ui->comboBoxAnalysis->setCurrentIndex(index);
} }
@ -45,6 +50,11 @@ int DiffLoadDialog::getLevel() const
return ui->comboBoxAnalysis->currentIndex(); return ui->comboBoxAnalysis->currentIndex();
} }
int DiffLoadDialog::getCompare() const
{
return ui->comboBoxCompare->currentIndex();
}
void DiffLoadDialog::on_buttonDiffOpen_clicked() void DiffLoadDialog::on_buttonDiffOpen_clicked()
{ {
QFileDialog dialog(this); QFileDialog dialog(this);

View File

@ -22,6 +22,7 @@ public:
QString getFileToOpen() const; QString getFileToOpen() const;
QString getPreviousDiffFile() const; QString getPreviousDiffFile() const;
int getLevel() const; int getLevel() const;
int getCompare() const;
signals: signals:
void startDiffing(); void startDiffing();

View File

@ -10,7 +10,7 @@
<x>0</x> <x>0</x>
<y>0</y> <y>0</y>
<width>636</width> <width>636</width>
<height>184</height> <height>226</height>
</rect> </rect>
</property> </property>
<property name="sizePolicy"> <property name="sizePolicy">
@ -20,7 +20,7 @@
</sizepolicy> </sizepolicy>
</property> </property>
<property name="windowTitle"> <property name="windowTitle">
<string notr="false">Select which file to compare.</string> <string>Select which file to compare.</string>
</property> </property>
<layout class="QVBoxLayout" name="verticalLayout_2"> <layout class="QVBoxLayout" name="verticalLayout_2">
<property name="sizeConstraint"> <property name="sizeConstraint">
@ -34,22 +34,6 @@
<item row="1" column="1"> <item row="1" column="1">
<widget class="QLineEdit" name="lineEditDiffFile"/> <widget class="QLineEdit" name="lineEditDiffFile"/>
</item> </item>
<item row="0" column="0">
<widget class="QLabel" name="fileToCompareLabel">
<property name="sizePolicy">
<sizepolicy hsizetype="Preferred" vsizetype="Preferred">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="toolTip">
<string>&lt;html&gt;&lt;head/&gt;&lt;body&gt;&lt;p&gt;File to compare to.&lt;/p&gt;&lt;/body&gt;&lt;/html&gt;</string>
</property>
<property name="text">
<string>File to compare (required)</string>
</property>
</widget>
</item>
<item row="0" column="2"> <item row="0" column="2">
<widget class="QPushButton" name="buttonFileOpen"> <widget class="QPushButton" name="buttonFileOpen">
<property name="text"> <property name="text">
@ -57,6 +41,19 @@
</property> </property>
</widget> </widget>
</item> </item>
<item row="1" column="2">
<widget class="QPushButton" name="buttonDiffOpen">
<property name="text">
<string>Select</string>
</property>
</widget>
</item>
<item row="2" column="1">
<widget class="QComboBox" name="comboBoxAnalysis"/>
</item>
<item row="0" column="1">
<widget class="QLineEdit" name="lineEditFileName"/>
</item>
<item row="1" column="0"> <item row="1" column="0">
<widget class="QLabel" name="previousDiffLabel"> <widget class="QLabel" name="previousDiffLabel">
<property name="sizePolicy"> <property name="sizePolicy">
@ -73,16 +70,6 @@
</property> </property>
</widget> </widget>
</item> </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"> <item row="2" column="0">
<widget class="QLabel" name="labelAnalysisLevel"> <widget class="QLabel" name="labelAnalysisLevel">
<property name="text"> <property name="text">
@ -90,8 +77,31 @@
</property> </property>
</widget> </widget>
</item> </item>
<item row="2" column="1"> <item row="0" column="0">
<widget class="QComboBox" name="comboBoxAnalysis"/> <widget class="QLabel" name="fileToCompareLabel">
<property name="sizePolicy">
<sizepolicy hsizetype="Preferred" vsizetype="Preferred">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="toolTip">
<string>&lt;html&gt;&lt;head/&gt;&lt;body&gt;&lt;p&gt;File to compare to.&lt;/p&gt;&lt;/body&gt;&lt;/html&gt;</string>
</property>
<property name="text">
<string>File to compare (required)</string>
</property>
</widget>
</item>
<item row="3" column="0">
<widget class="QLabel" name="labelCompareLogic">
<property name="text">
<string>Compare Logic</string>
</property>
</widget>
</item>
<item row="3" column="1">
<widget class="QComboBox" name="comboBoxCompare"/>
</item> </item>
</layout> </layout>
</item> </item>

View File

@ -13,11 +13,10 @@ DiffWaitDialog::DiffWaitDialog(QWidget *parent)
{ {
ui->setupUi(this); ui->setupUi(this);
setWindowFlags(windowFlags() & (~Qt::WindowContextHelpButtonHint)); setWindowFlags(windowFlags() & (~Qt::WindowContextHelpButtonHint));
setModal(true);
ui->lineEditNFuncs->setReadOnly(true); ui->lineEditNFuncs->setReadOnly(true);
ui->lineEditMatches->setReadOnly(true); ui->lineEditMatches->setReadOnly(true);
ui->lineEditEstimatedTime->setReadOnly(true);
ui->lineEditElapsedTime->setReadOnly(true);
ui->lineEditOriginal->setReadOnly(true); ui->lineEditOriginal->setReadOnly(true);
ui->lineEditModified->setReadOnly(true); ui->lineEditModified->setReadOnly(true);
ui->progressBar->setValue(0); ui->progressBar->setValue(0);
@ -34,11 +33,11 @@ DiffWaitDialog::~DiffWaitDialog()
if (bDiff && bDiff->isRunning()) { if (bDiff && bDiff->isRunning()) {
bDiff->cancel(); bDiff->cancel();
bDiff->wait(); bDiff->wait();
delete bDiff;
} }
delete bDiff;
} }
void DiffWaitDialog::show(QString original, QString modified, int level) void DiffWaitDialog::show(QString original, QString modified, int level, int compare)
{ {
connect(this, &DiffWaitDialog::cancelJob, bDiff, &BinDiff::cancel); connect(this, &DiffWaitDialog::cancelJob, bDiff, &BinDiff::cancel);
connect(bDiff, &BinDiff::progress, this, &DiffWaitDialog::onProgress); connect(bDiff, &BinDiff::progress, this, &DiffWaitDialog::onProgress);
@ -49,6 +48,7 @@ void DiffWaitDialog::show(QString original, QString modified, int level)
ui->lineEditModified->setText(modified); ui->lineEditModified->setText(modified);
bDiff->setAnalysisLevel(level); bDiff->setAnalysisLevel(level);
bDiff->setCompareLogic(compare);
bDiff->setFile(modified); bDiff->setFile(modified);
eTimer.restart(); eTimer.restart();
timer.setSingleShot(false); timer.setSingleShot(false);
@ -80,10 +80,12 @@ void DiffWaitDialog::onCompletion()
{ {
timer.stop(); timer.stop();
auto results = new DiffWindow(bDiff, parentWidget()); if (bDiff->hasData()) {
bDiff = nullptr; auto results = new DiffWindow(bDiff, parentWidget());
bDiff = nullptr;
results->showMaximized();
}
results->showMaximized();
close(); close();
} }
@ -102,4 +104,5 @@ void DiffWaitDialog::on_buttonBox_rejected()
{ {
timer.stop(); timer.stop();
emit cancelJob(); emit cancelJob();
close();
} }

View File

@ -22,7 +22,7 @@ public:
explicit DiffWaitDialog(QWidget *parent = nullptr); explicit DiffWaitDialog(QWidget *parent = nullptr);
~DiffWaitDialog(); ~DiffWaitDialog();
void show(QString original, QString modified, int level); void show(QString original, QString modified, int level, int compare);
public slots: public slots:
void onProgress(BinDiffStatusDescription status); void onProgress(BinDiffStatusDescription status);

View File

@ -41,7 +41,7 @@
<item> <item>
<layout class="QGridLayout" name="gridLayout"> <layout class="QGridLayout" name="gridLayout">
<item row="3" column="1"> <item row="3" column="1">
<widget class="QLineEdit" name="lineEditElapsedTime"/> <widget class="QLabel" name="lineEditElapsedTime"/>
</item> </item>
<item row="1" column="1"> <item row="1" column="1">
<widget class="QLineEdit" name="lineEditModified"/> <widget class="QLineEdit" name="lineEditModified"/>
@ -98,7 +98,7 @@
</widget> </widget>
</item> </item>
<item row="2" column="1"> <item row="2" column="1">
<widget class="QLineEdit" name="lineEditEstimatedTime"/> <widget class="QLabel" name="lineEditEstimatedTime"/>
</item> </item>
</layout> </layout>
</item> </item>

View File

@ -56,7 +56,26 @@ QVariant DiffMatchModel::data(const QModelIndex &index, int role) const
} }
case Qt::ToolTipRole: { case Qt::ToolTipRole: {
return entry.simtype; switch (index.column()) {
case NameOrig:
return entry.original.name;
case SizeOrig:
return QString::asprintf("%llu (%#llx)", entry.original.linearSize,
entry.original.linearSize);
case AddressOrig:
return RzAddressString(entry.original.offset);
case Similarity:
return entry.simtype;
case AddressMod:
return RzAddressString(entry.modified.offset);
case SizeMod:
return QString::asprintf("%llu (%#llx)", entry.modified.linearSize,
entry.modified.linearSize);
case NameMod:
return entry.modified.name;
default:
return QVariant();
}
} }
case Qt::BackgroundRole: { case Qt::BackgroundRole: {
@ -126,6 +145,8 @@ QVariant DiffMismatchModel::data(const QModelIndex &index, int role) const
const FunctionDescription &entry = list->at(index.row()); const FunctionDescription &entry = list->at(index.row());
switch (role) { switch (role) {
case Qt::ToolTipRole:
/* fall-thru */
case Qt::DisplayRole: case Qt::DisplayRole:
switch (index.column()) { switch (index.column()) {
case FuncName: case FuncName:
@ -150,10 +171,6 @@ QVariant DiffMismatchModel::data(const QModelIndex &index, int role) const
return QVariant(); return QVariant();
} }
case Qt::ToolTipRole: {
return entry.name;
}
default: default:
return QVariant(); return QVariant();
} }
@ -194,6 +211,7 @@ DiffWindow::DiffWindow(BinDiff *bd, QWidget *parent)
: QDialog(parent), ui(new Ui::DiffWindow), bDiff(bd) : QDialog(parent), ui(new Ui::DiffWindow), bDiff(bd)
{ {
ui->setupUi(this); ui->setupUi(this);
setModal(true);
ui->comboBoxShowInfo->addItem(tr("Summary")); ui->comboBoxShowInfo->addItem(tr("Summary"));
ui->comboBoxShowInfo->addItem(tr("AAAA")); ui->comboBoxShowInfo->addItem(tr("AAAA"));
@ -213,22 +231,16 @@ DiffWindow::DiffWindow(BinDiff *bd, QWidget *parent)
// Matches Table // Matches Table
ui->tableViewMatch->setModel(modelMatch); ui->tableViewMatch->setModel(modelMatch);
ui->tableViewMatch->sortByColumn(DiffMatchModel::Similarity, Qt::AscendingOrder); ui->tableViewMatch->sortByColumn(DiffMatchModel::Similarity, Qt::AscendingOrder);
ui->tableViewMatch->verticalHeader()->hide();
ui->tableViewMatch->horizontalHeader()->setSectionResizeMode(QHeaderView::Stretch);
ui->tableViewMatch->setContextMenuPolicy(Qt::CustomContextMenu); ui->tableViewMatch->setContextMenuPolicy(Qt::CustomContextMenu);
// Deletion Table // Deletion Table
ui->tableViewRem->setModel(modelDel); ui->tableViewRem->setModel(modelDel);
ui->tableViewRem->sortByColumn(DiffMismatchModel::FuncName, Qt::AscendingOrder); ui->tableViewRem->sortByColumn(DiffMismatchModel::FuncName, Qt::AscendingOrder);
ui->tableViewRem->verticalHeader()->hide();
ui->tableViewRem->horizontalHeader()->setSectionResizeMode(QHeaderView::Stretch);
ui->tableViewRem->setContextMenuPolicy(Qt::CustomContextMenu); ui->tableViewRem->setContextMenuPolicy(Qt::CustomContextMenu);
// Addition Table // Addition Table
ui->tableViewAdd->setModel(modelAdd); ui->tableViewAdd->setModel(modelAdd);
ui->tableViewAdd->sortByColumn(DiffMismatchModel::FuncName, Qt::AscendingOrder); ui->tableViewAdd->sortByColumn(DiffMismatchModel::FuncName, Qt::AscendingOrder);
ui->tableViewAdd->verticalHeader()->hide();
ui->tableViewAdd->horizontalHeader()->setSectionResizeMode(QHeaderView::Stretch);
ui->tableViewAdd->setContextMenuPolicy(Qt::CustomContextMenu); ui->tableViewAdd->setContextMenuPolicy(Qt::CustomContextMenu);
} }

View File

@ -64,7 +64,42 @@
</attribute> </attribute>
<layout class="QVBoxLayout" name="verticalLayout_3"> <layout class="QVBoxLayout" name="verticalLayout_3">
<item> <item>
<widget class="QTableView" name="tableViewMatch"/> <widget class="CutterTreeView" name="tableViewMatch">
<attribute name="title">
<string>Matches</string>
</attribute>
<property name="styleSheet">
<string notr="true">CutterTreeView::item
{
padding-top: 1px;
padding-bottom: 1px;
}</string>
</property>
<property name="frameShape">
<enum>QFrame::NoFrame</enum>
</property>
<property name="lineWidth">
<number>0</number>
</property>
<property name="horizontalScrollBarPolicy">
<enum>Qt::ScrollBarAsNeeded</enum>
</property>
<property name="sizeAdjustPolicy">
<enum>QAbstractScrollArea::AdjustToContents</enum>
</property>
<property name="autoScroll">
<bool>true</bool>
</property>
<property name="horizontalScrollMode">
<enum>QAbstractItemView::ScrollPerPixel</enum>
</property>
<property name="indentation">
<number>8</number>
</property>
<property name="sortingEnabled">
<bool>true</bool>
</property>
</widget>
</item> </item>
</layout> </layout>
</widget> </widget>
@ -74,7 +109,42 @@
</attribute> </attribute>
<layout class="QVBoxLayout" name="verticalLayoutMismatchRem"> <layout class="QVBoxLayout" name="verticalLayoutMismatchRem">
<item> <item>
<widget class="QTableView" name="tableViewRem"/> <widget class="CutterTreeView" name="tableViewRem">
<attribute name="title">
<string>Matches</string>
</attribute>
<property name="styleSheet">
<string notr="true">CutterTreeView::item
{
padding-top: 1px;
padding-bottom: 1px;
}</string>
</property>
<property name="frameShape">
<enum>QFrame::NoFrame</enum>
</property>
<property name="lineWidth">
<number>0</number>
</property>
<property name="horizontalScrollBarPolicy">
<enum>Qt::ScrollBarAsNeeded</enum>
</property>
<property name="sizeAdjustPolicy">
<enum>QAbstractScrollArea::AdjustToContents</enum>
</property>
<property name="autoScroll">
<bool>true</bool>
</property>
<property name="horizontalScrollMode">
<enum>QAbstractItemView::ScrollPerPixel</enum>
</property>
<property name="indentation">
<number>8</number>
</property>
<property name="sortingEnabled">
<bool>true</bool>
</property>
</widget>
</item> </item>
</layout> </layout>
</widget> </widget>
@ -84,7 +154,42 @@
</attribute> </attribute>
<layout class="QVBoxLayout" name="verticalLayoutMismatchAdd"> <layout class="QVBoxLayout" name="verticalLayoutMismatchAdd">
<item> <item>
<widget class="QTableView" name="tableViewAdd"/> <widget class="CutterTreeView" name="tableViewAdd">
<attribute name="title">
<string>Matches</string>
</attribute>
<property name="styleSheet">
<string notr="true">CutterTreeView::item
{
padding-top: 1px;
padding-bottom: 1px;
}</string>
</property>
<property name="frameShape">
<enum>QFrame::NoFrame</enum>
</property>
<property name="lineWidth">
<number>0</number>
</property>
<property name="horizontalScrollBarPolicy">
<enum>Qt::ScrollBarAsNeeded</enum>
</property>
<property name="sizeAdjustPolicy">
<enum>QAbstractScrollArea::AdjustToContents</enum>
</property>
<property name="autoScroll">
<bool>true</bool>
</property>
<property name="horizontalScrollMode">
<enum>QAbstractItemView::ScrollPerPixel</enum>
</property>
<property name="indentation">
<number>8</number>
</property>
<property name="sortingEnabled">
<bool>true</bool>
</property>
</widget>
</item> </item>
</layout> </layout>
</widget> </widget>
@ -151,6 +256,14 @@
</property> </property>
</action> </action>
</widget> </widget>
<customwidgets>
<customwidget>
<class>CutterTreeView</class>
<extends>QTreeView</extends>
<header>widgets/CutterTreeView.h</header>
<container>1</container>
</customwidget>
</customwidgets>
<resources/> <resources/>
<connections/> <connections/>
</ui> </ui>