项目配置:
QT += core gui
greaterThan(QT_MAJOR_VERSION, 4): QT += widgets
TARGET = bindiff-qt
TEMPLATE = app
*-g++*:QMAKE_CXXFLAGS += -Wall -Weffc++ -Wextra -Wconversion -Wsign-conversion -std=c++14
SOURCES += main.cpp\
mainwindow.cpp \
binfileview.cpp
HEADERS += mainwindow.h \
binfileview.h
FORMS += mainwindow.ui
OTHER_FILES += license.txt
INSTALLS += target
unix{
target.path = /bin
message( The executable will be installed to $$target.path )
}
main.cpp
#include "mainwindow.h"
#include
#include
int main( int argc, char* argv[] )
{
QFileInfo execFile( argv[0] );
QCoreApplication::setApplicationName( execFile.fileName() );
QApplication a( argc, argv );
MainWindow w;
w.show();
return a.exec();
}
mainwindow.h/cpp/ui
#ifndef MAINWINDOW_H
#define MAINWINDOW_H
#include
#include
namespace Ui {
class MainWindow;
}
class QFile;
class BinFileView;
struct FileModel
{
FileModel( QFile* file, uchar* mmap ) : _file( file ), _mmap( mmap ) {}
QFile* _file;
uchar* _mmap;
};
class MainWindow : public QMainWindow
{
Q_OBJECT
public:
explicit MainWindow( QWidget* parent = nullptr );
~MainWindow();
private slots:
void open( BinFileView* );
void open( const QString&, BinFileView* view = nullptr );
void updateDiff( BinFileView* );
void on_actionE_xit_triggered();
private: // No copying
MainWindow( const MainWindow& );
MainWindow& operator=( const MainWindow& );
private: // Data
Ui::MainWindow* ui;
QMap _files;
uchar* _diffMap;
qint64 _diffMapSize;
};
#endif // MAINWINDOW_H
#include "mainwindow.h"
#include "ui_mainwindow.h"
#include
#include
#include
#include
MainWindow::MainWindow( QWidget *parent ) :
QMainWindow( parent ),
ui( new Ui::MainWindow ),
_diffMap( nullptr ),
_diffMapSize( 0 )
{
ui->setupUi( this );
setWindowTitle( QCoreApplication::applicationName() );
// ui->binFileView1->setAcceptDrops( true );
// ui->binFileView2->setAcceptDrops( true );
ui->binFileView1->setFont( QFont( "Monospace", 10 ) );
ui->binFileView2->setFont( QFont( "Monospace", 10 ) );
// Cross-connect vertical & horizontal scroll bars
connect( ui->binFileView1->verticalScrollBar(), \
SIGNAL( valueChanged( int ) ), \
ui->binFileView2->verticalScrollBar(), \
SLOT( setValue( int ) ) );
connect( ui->binFileView2->verticalScrollBar(), \
SIGNAL( valueChanged( int ) ), \
ui->binFileView1->verticalScrollBar(), \
SLOT( setValue( int ) ) );
connect( ui->binFileView1->horizontalScrollBar(), \
SIGNAL( valueChanged( int ) ), \
ui->binFileView2->horizontalScrollBar(), \
SLOT( setValue( int ) ) );
connect( ui->binFileView2->horizontalScrollBar(), \
SIGNAL( valueChanged( int ) ), \
ui->binFileView1->horizontalScrollBar(), \
SLOT( setValue( int ) ) );
// to maintain consistent width for both views
connect( ui->binFileView1, SIGNAL( defaultVisualsChanged( BinFileView* ) ), \
ui->binFileView2, SLOT( synchronizeVisuals( BinFileView* ) ) );
connect( ui->binFileView2, SIGNAL( defaultVisualsChanged( BinFileView* ) ), \
ui->binFileView1, SLOT( synchronizeVisuals( BinFileView* ) ) );
// File drag & drop signals
connect( ui->binFileView1, SIGNAL( fileDropped( QString, BinFileView* ) ), \
this, SLOT( open( QString, BinFileView* ) ) );
connect( ui->binFileView2, SIGNAL( fileDropped( QString, BinFileView* ) ), \
this, SLOT( open( QString, BinFileView* ) ) );
// And view's file ctx menu signals
connect( ui->binFileView1, SIGNAL( fileOpenRequested( BinFileView* ) ), \
this, SLOT( open( BinFileView* ) ) );
connect( ui->binFileView2, SIGNAL( fileOpenRequested( BinFileView* ) ), \
this, SLOT( open( BinFileView* ) ) );
// On demand (i.e. via changed content of view's data) requested diffing
connect( ui->binFileView1, SIGNAL( fileViewContentChanged( BinFileView* ) ), \
this, SLOT( updateDiff( BinFileView* ) ), Qt::DirectConnection );
connect( ui->binFileView2, SIGNAL( fileViewContentChanged( BinFileView* ) ), \
this, SLOT( updateDiff( BinFileView* ) ), Qt::DirectConnection );
// Get the arguments
if( QCoreApplication::arguments().size() == 3 ) {
open( QCoreApplication::arguments().at( 1 ), ui->binFileView1 );
open( QCoreApplication::arguments().at( 2 ), ui->binFileView2 );
}
}
MainWindow::~MainWindow()
{
delete ui;
//代码中使用了内存映射,所以需要对资源及时释放
if( !_files.empty() ) {
for( const auto f : _files ) {
f._file->unmap( f._mmap );
f._file->close();
delete f._file;
}
}
if( _d