diff --git a/README.md b/README.md index c698988..38e467a 100644 --- a/README.md +++ b/README.md @@ -1,13 +1,181 @@ -Qt plugins for DFHack -===================== +DwarfExplorer +============= +A DFHack plugin for browsing Dwarf Fortress internal structures (Windows/Linux). -DFHack plugins for using Qt widgets. +![](images/dwarf_explorer.png) -How to build ------------- +*NOTE:* Linux version is done but it will be out in a few weeks. -Copy/link/clone this directory as a subdirectory in dfhack's `plugins` -directory. Add the subdirectory (e.g. a `add_subdirectory(qt)` line) in -`plugins/CMakeLists.custom.txt`. Then follow DFHack instructions for building -plugins. +Features +-------- +* Graphical viewer for all Dwarf Fortress structures known from DFHack. +* Open any individual structure in a new window for easy understanding. +* All structure types supported (vectors, arrays, pointers, enums, unions, bitfields, etc). +* Hexadecimal memory viewer for Dwarf Fortress process memory. +* Show comments and 'refers-to' (if defined) attributes for fields in structures. +* Show the dfhack xml file where each structure is defined. +* Stores opened df structures so you can track evolution of the structures in time (rather primitive right now). +* Automatic decoding of enums, bitfields, coordinates and language names. +* Decoding of derived classes showing its hyerarachy. + + + + +Motivation +---------- +We all know gm-editor, the wonderful in game browser invaluable for researching Dwarf Fortress internal structures. Dwarf Explorer does something similar with the following advantages: + +* A treeview allows a better understanding of a structure. You can expand/compact fields as you wish.
+gm-editor changes to a new screen each time you move down in the structure. +* DFHack has a hex memory viewer, but is a command line one. Dwarf Explorer allows you to open a hex memory viewer for each field of a df structure and even follow pointers. + +Dwarf Explorer has also some disavantadges: +* Right now you can't change values in Dwarf Fortress memory. + This is something that will change in future versions of the plugin.
+ Use gm-editor for that task. + + + +Qt DFHack plugins, what sorcery is this? +---------------------------------------- +You need to thanks Clement. Yes that Clement, the one that maintains Dwarf Therapist. + +He found a method for loading Qt inside DFHack, so you can create multiplatform graphical applications running in the same process as Dwarf Fortress. + +Think about that. You get access to all the abilities that DFHack provides for plugins, and you can show all that information graphically! + + + +How do I install the plugin? +---------------------- + +First, download the plugin from github. You need to download the plugin for the dfhack version that you have installed in your computer. + +You will get four files: +* `dwarfexplorer.plug.dll` (.so in Linux). +* `Qt5Core.dll` +* `Qt5Gui.dll` +* `Qt5Widgets.dll` + +The first one is the dfhack plugin and you need to put in the folder `/hack/plugins` of your Dwarf Fortress directory. + +The other ones are Qt dynamic libraries that need to be installed in your Dwarf Fortress directory. + +How do I run the plugin? +---------------------- + +Dwarf Explorer only works in PAUSED games. + +There's no way that the plugin can track all the data that changes in Dwarf Fortress in real time, so the plugin automatically pauses the game, gets the data from DF and shows it. + +Launch Dwarf Fortress (and DFHack of course) and load your world. +In the dfhack console type: + +`enable qapplication` + +This loads the Qt dynamic libraries into Dwarf Fortress process. + +After that, launch the graphical viewer typing + +`dwarfexplorer` + +The plugin window will be displayed without any data, just telling you that Dwarf Fortress is running. + +![](images/1.gif) + + +You need to pause Dwarf Fortress using the Suspend button in the toolbar. When you do this, Dwarf Fortress will pause and the plugin window will display all the known global variables (aka df.global). + +![](images/2.gif) + +You can now browse all the data, view memory, open new windows, etc. When you are done, press the resume button in the toolbar and continue playing. + +![](images/6.gif) + +Where's the data? +---------------------- +The most important global variable is world (df.global.world). This structure has all the data that your fortress uses. So, navigate to the bottom of the windows and locate world. + +Then expand the tree and marvel about all the glorious Dwarf Fortress data. + +If your tree gets convoluted with too much data, you can also open any structure in a new window by selecting it and using the menu `Window->Open in new window`. + +![](images/3.gif) + +Some DF data examples +---------------------- + +* Where are my dwarves?
+ They are in the vector df.global.world.units.active + +* How much vermin exists in my embark?
+ Check vector df.global.world.vermin.all. + +* What about the fortress buildings?
+ vector df.global.world.buildings.all + +* Where is the rest of the world data?
+ It's in the pointer df.global.world.world_data + +* What's the tallest mountain in the world?
+ Look for the field height in df.global.world.world_data.mountain_peaks vector + +The memory viewer +---------------------- +As you browse Dwarf Fortress data, you will encounter a lot of unknow structures (data where we know the C++ type of the field but we don't know its meaning related to the game). + +For every field or df structure, you can always see the Dwarf Fortress process memory where this data resides. To do that, select the field and click in the menu `Window->Open address in hex viewer`. + +A memory viewer will open at the address where the field is stored. + +![](images/4.gif) + +For some C++ structures like vectors or pointers, the data has a another level of indirection. + +If you open a memory viewer for a vector you will not get the real data. This is because the internal structure of a vector consists of three pointers, being the first pointer the one that points to the data beginning. + +To do this operation easier, just select `Window->Open destination address in hex viewer` and you will get the hex memory viewer pointing to the real data. + +![](images/5.gif) + +Does it run with the LNP (Lazy Newcomers Pack)? +---------------------------------------------- +Yes as long as your LNP version matches the plugin version. + +If the plugin is compiled for DFHack 0.44.12, your LNP must be 0.44.12 also. + +No MacOS? +---------------------------------------------- +I've zero knowledge of Macs. In theory the code should be portable across operating systems (Qt strenght). But it seems that there are problems in that platform. + +What happens when Dwarf Fortress / DFHack changes? +---------------------- +The plugin code is generated automatically from DFHack `codegen.out.xml` file using a tool.
+Each time that a new DFHack version will be released, I'll update the plugin accordingly. + +Bugs, suggestion, etc +---------------------- +You can use github issues or contact me by irc in `#dfhack` in freenode. + +Closing thoughts +---------------------- + +*The real *FUN* is not in your fortress but in the code!!!!* + + +I hope this tool will encourage more people to do researching in Dwarf Fortress. It'a fascinating puzzle ready to be assembled. +You can try to find relationship between known and unknown data, discover new structures or fields, etc. Then, open a pull request in https://github.com/DFHack/df-structures +for providing that valuable info to the community. + +When you starts digging into Dwarf Fortress internals, you wil be hooked. You can even try to advance to the next level and do some reverse engineering of Dwarf Fortress code using IDA or Ghidra. + + + + + +Thanks +---------------------- +Clement (https://github.com/cvuchener) for providing the wonderful framework in which this plugin runs. + +lethosor (https://github.com/lethosor) and all the wonderful people of `#dfhack` channel in freenode. \ No newline at end of file diff --git a/dwarfexplorer/CMakeLists.txt b/dwarfexplorer/CMakeLists.txt index 62f4123..4c31ff8 100644 --- a/dwarfexplorer/CMakeLists.txt +++ b/dwarfexplorer/CMakeLists.txt @@ -21,6 +21,7 @@ set(DWARFEXPLORER_SOURCES EventProxy.cpp MainWindow.cpp dfstructure_window.cpp + hexviewer_window.cpp QtModel/df_model.cpp QtModel/df_model_data_from_structure.cpp QtModel/df_model_data_from_type.cpp @@ -30,6 +31,7 @@ set(DWARFEXPLORER_SOURCES QtModel/df_model_pointer.cpp QtModel/df_model_util.cpp QtModel/df_model_df_array.cpp + QtModel/df_proxy_model.cpp generated/offsets_cache.cpp generated/fill_nodes.cpp generated/fill_offsets.cpp @@ -59,7 +61,9 @@ qt5_wrap_cpp(DWARFEXPLORER_MOC_SOURCES EventProxy.h MainWindow.h df_model.h + QtModel/df_proxy_model.h dfstructure_window.h + hexviewer_window.h QHexView/document/commands/hexcommand.h QHexView/document/commands/insertcommand.h QHexView/document/commands/removecommand.h @@ -82,6 +86,6 @@ qt5_wrap_ui(DWARFEXPLORER_UI_SOURCES DFHACK_PLUGIN(dwarfexplorer - ${DWARFEXPLORER_SOURCES} ${DWARFEXPLORER_MOC_SOURCES} ${DWARFEXPLORER_UI_SOURCES} + ${DWARFEXPLORER_SOURCES} ${DWARFEXPLORER_MOC_SOURCES} ${DWARFEXPLORER_UI_SOURCES} ${RSCS} LINK_LIBRARIES Qt5::Core Qt5::Widgets) target_include_directories(dwarfexplorer PRIVATE ${CMAKE_CURRENT_BINARY_DIR}) diff --git a/dwarfexplorer/MainWindow.cpp b/dwarfexplorer/MainWindow.cpp index f42185e..c07e1c2 100644 --- a/dwarfexplorer/MainWindow.cpp +++ b/dwarfexplorer/MainWindow.cpp @@ -149,9 +149,10 @@ void MainWindow::on_suspend_action_triggered() // void MainWindow::on_resume_action_triggered() { - for (DFStructure_Window* child_window: m_child_window_list) - if (child_window != nullptr) - child_window->set_outdated(); +// for (DFStructure_Window* child_window: m_child_window_list) +// if (child_window != nullptr) +// child_window->set_outdated(); + emit resumed_signal(); ui->stackedWidget->setCurrentIndex(0); ui->resume_action->setEnabled(false); @@ -165,24 +166,6 @@ void MainWindow::on_resume_action_triggered() m_suspended = false; } -// -//--------------------------------------------------------------------------------------- -// -void MainWindow::remove_child_window(DFStructure_Window *p_child_window) -{ - for (auto i = 0; i < m_child_window_list.size(); i++) - if (m_child_window_list[i] == p_child_window) - m_child_window_list[i] = nullptr; -} - -// -//--------------------------------------------------------------------------------------- -// -void MainWindow::add_child_window(DFStructure_Window *p_child_window) -{ - m_child_window_list.push_back(p_child_window); -} - // //--------------------------------------------------------------------------------------- // @@ -264,7 +247,7 @@ void MainWindow::on_actionOpen_in_new_window_triggered() new_window_name.append(n_root->m_path); // Add the window to the list of child windows - m_child_window_list.push_back(new_window); + //m_child_window_list.push_back(new_window); // Show the window new_window->setWindowTitle(QString::fromStdString(new_window_name)); @@ -292,24 +275,13 @@ void MainWindow::on_actionOpen_in_hex_viewer_triggered() // Get the selected node rdf::NodeBase* node = dynamic_cast(model->nodeFromIndex(selected_node)); - auto the_data = reinterpret_cast(node->m_address); - auto the_size = std::min(std::size_t(4096), size_of_DF_Type(node->m_df_type)); - the_size = std::max(std::size_t(4096), the_size); - - QHexDocument* document = QHexDocument::fromMemory(the_data, the_size); - QHexView* hexview = new QHexView(); - hexview->setDocument(document); - hexview->setReadOnly(true); - document->setBaseAddress(node->m_address); - //QHexViewer_Window* hex_window = new QHexViewer_Window(this); - - //QHexView* hex_view = hex_window->get_hexview(); - //hex_view->set_base_address(node->m_address); - //hex_view->setData(new QHexView::DataStorageArray(data)); + uint64_t the_address = node->m_address; + auto the_data = reinterpret_cast(node->m_address); + auto the_size = std::min(std::size_t(4096), size_of_DF_Type(node->m_df_type)); + the_size = std::max(std::size_t(4096), the_size); - // window title - auto the_number = QString::fromStdString(to_hex(node->m_address)); - hexview->setWindowTitle("Memory viewer - " + the_number); + // Create the window and show it + auto hexview = new QHexViewer_Window(this, the_address, the_data, the_size); hexview->show(); } @@ -335,21 +307,14 @@ void MainWindow::on_actionOpenPointer_in_hex_viewer_triggered() rdf::NodeBase* node_base = model->nodeFromIndex(selected_node); uint64_t* pointer_address = reinterpret_cast(node_base->m_address); - uint64_t item_address = *pointer_address; + uint64_t the_address = *pointer_address; - auto the_data = reinterpret_cast(item_address); + auto the_data = reinterpret_cast(the_address); auto the_size = std::min(std::size_t(4096), size_of_DF_Type(node_base->m_df_type)); the_size = std::max(std::size_t(4096), the_size); - QHexDocument* document = QHexDocument::fromMemory(the_data, the_size); - document->setBaseAddress(item_address); - QHexView* hexview = new QHexView(); - hexview->setDocument(document); - hexview->setReadOnly(true); - - // Window tittle - auto the_number = QString::fromStdString(to_hex(item_address)); - hexview->setWindowTitle("Memory viewer - " + the_number); + // Create the window and show it + auto hexview = new QHexViewer_Window(this, the_address, the_data, the_size); hexview->show(); } @@ -364,3 +329,7 @@ void MainWindow::closeEvent(QCloseEvent* p_event) // Do the thing p_event->accept(); } + +//void MainWindow::resumed_signal() +//{ +//} diff --git a/dwarfexplorer/MainWindow.h b/dwarfexplorer/MainWindow.h index db7c329..b04d819 100644 --- a/dwarfexplorer/MainWindow.h +++ b/dwarfexplorer/MainWindow.h @@ -24,16 +24,23 @@ #include #include - +#include #include #include #include +#include #include "df_model.h" +#include "QtModel/df_proxy_model.h" class EventProxy; - namespace Ui { class MainWindow; } + namespace Ui + { + class MainWindow; + } + + class DFStructure_Window; class MainWindow: public QMainWindow { @@ -42,20 +49,26 @@ explicit MainWindow(std::shared_ptr &&proxy, QWidget *parent = nullptr); ~MainWindow() override; + signals: + void resumed_signal(); + private slots: void on_suspend_action_triggered(); void on_resume_action_triggered(); - - void updateUnitModel(); - void clearUnitModel(); void on_treeView_expanded(const QModelIndex& p_index); void on_actionOpen_in_new_window_triggered(); void on_actionOpen_in_hex_viewer_triggered(); void on_actionOpenPointer_in_hex_viewer_triggered(); + void on_filter_textChanged(const QString &arg1); + protected: + void closeEvent(QCloseEvent* p_close_event); private: - std::unique_ptr ui; - std::shared_ptr event_proxy; - DF_Model* model; + std::unique_ptr ui; + std::shared_ptr event_proxy; + std::unique_ptr m_model; + std::unique_ptr m_proxy_model; + DFHack::CoreSuspender* m_core_suspender; + bool m_suspended; }; #endif diff --git a/dwarfexplorer/MainWindow.ui b/dwarfexplorer/MainWindow.ui index 4a548a7..324324d 100644 --- a/dwarfexplorer/MainWindow.ui +++ b/dwarfexplorer/MainWindow.ui @@ -13,174 +13,150 @@ Dwarf Explorer - df.global - - - - - - - - - - - - 0 - 0 - - - - Dwarf Fortress is running. Press 'Suspend' button to enable Dwarf Explorer operation - - - Qt::AlignCenter - - - - - - - - - - - - 100 - 100 - - - - 25 - - - 40 - - - 120 - - - - - - - - - - - - - 0 - 0 - 932 - 25 - - - - - File - - - - - - Window - - - - - - - - - - - toolBar - - - Qt::ToolButtonTextUnderIcon - - - TopToolBarArea - - - false - - - - - - - - .. - - - Suspend - - - Suspend DF so data can be accessed - - - - - - .. - - - Resume - - - Resume DF - - - - - - Exit - - - - - Open in new window - - - - - Open address in hex viewer - - - - - Open destination address in hex viewer - - - - - - + + + + + + + + + + + 0 + 0 + + + + Dwarf Fortress is running. Press 'Suspend' button to enable Dwarf Explorer operation + + + Qt::AlignCenter + + + + + + + + + + + + 100 + 100 + + + + 25 + + + 40 + + + 120 + + + + + + + + + + + + + 0 + 0 + 932 + 25 + + + + + File + + + + + + Window + + + + + + + + + + + toolBar + + + Qt::ToolButtonTextUnderIcon + + + TopToolBarArea + + + false + + + + + + + + + :/Breezeicons-actions-22-media-playback-pause.png + :/Breezeicons-actions-22-media-playback-pause.png + + + + Suspend + + + Suspend DF so data can be accessed + + + + + + :/Breezeicons-actions-22-media-playback-start.png + :/Breezeicons-actions-22-media-playback-start.png + + + + Resume + + + Resume DF + + + + + Exit + + + + + Open in new window + + + + + Open address in hex viewer + + + + + Open destination address in hex viewer + + + + + + diff --git a/dwarfexplorer/QHexView/document/buffer/qhexbuffer.cpp b/dwarfexplorer/QHexView/document/buffer/qhexbuffer.cpp index 1f15d3f..1c10d3e 100644 --- a/dwarfexplorer/QHexView/document/buffer/qhexbuffer.cpp +++ b/dwarfexplorer/QHexView/document/buffer/qhexbuffer.cpp @@ -3,16 +3,23 @@ QHexBuffer::QHexBuffer(QObject *parent) : QObject(parent) { } -uchar QHexBuffer::at(int idx) { return this->read(idx, 1)[0]; } -bool QHexBuffer::isEmpty() const { return this->length() <= 0; } +uchar QHexBuffer::at(uint64_t idx) +{ + return this->read(idx, 1)[0]; +} -void QHexBuffer::replace(int offset, const QByteArray &data) +bool QHexBuffer::isEmpty() const +{ + return this->length() <= 0; +} + +void QHexBuffer::replace(uint64_t offset, const QByteArray &data) { this->remove(offset, data.length()); this->insert(offset, data); } -void QHexBuffer::read(char *data, int size) +void QHexBuffer::read(char *data, uint64_t size) { QBuffer* buffer = new QBuffer(this); buffer->setData(data, size); @@ -32,5 +39,4 @@ void QHexBuffer::read(const QByteArray &ba) buffer->setData(ba); this->read(buffer); -} - +} \ No newline at end of file diff --git a/dwarfexplorer/QHexView/document/buffer/qhexbuffer.h b/dwarfexplorer/QHexView/document/buffer/qhexbuffer.h index 07a96fe..301cb33 100644 --- a/dwarfexplorer/QHexView/document/buffer/qhexbuffer.h +++ b/dwarfexplorer/QHexView/document/buffer/qhexbuffer.h @@ -13,18 +13,18 @@ class QHexBuffer : public QObject bool isEmpty() const; public: - virtual uchar at(int idx); - virtual void replace(int offset, const QByteArray& data); - virtual void read(char* data, int size); - virtual void read(const QByteArray& ba); + virtual uchar at(uint64_t idx); + virtual void replace(uint64_t offset, const QByteArray& data); + virtual void read(char* data, uint64_t size); + virtual void read(const QByteArray& ba); public: - virtual int length() const = 0; - virtual void insert(int offset, const QByteArray& data) = 0; - virtual void remove(int offset, int length) = 0; - virtual QByteArray read(int offset, int length) = 0; - virtual void read(QIODevice* iodevice) = 0; - virtual void write(QIODevice* iodevice) = 0; + virtual uint64_t length() const = 0; + virtual void insert(uint64_t offset, const QByteArray& data) = 0; + virtual void remove(uint64_t offset, uint64_t length) = 0; + virtual QByteArray read(uint64_t offset, uint64_t length) = 0; + virtual void read(QIODevice* iodevice) = 0; + virtual void write(QIODevice* iodevice) = 0; }; #endif // QHEXBUFFER_H diff --git a/dwarfexplorer/QHexView/document/buffer/qmemorybuffer.h b/dwarfexplorer/QHexView/document/buffer/qmemorybuffer.h index 11cd71a..881ccce 100644 --- a/dwarfexplorer/QHexView/document/buffer/qmemorybuffer.h +++ b/dwarfexplorer/QHexView/document/buffer/qmemorybuffer.h @@ -9,13 +9,14 @@ class QMemoryBuffer : public QHexBuffer public: explicit QMemoryBuffer(QObject *parent = nullptr); - uchar at(int idx) override; - int length() const override; - void insert(int offset, const QByteArray& data) override; - void remove(int offset, int length) override; - QByteArray read(int offset, int length) override; - void read(QIODevice* device) override; - void write(QIODevice* device) override; + + uchar at(uint64_t idx) override; + uint64_t length() const override; + void insert(uint64_t offset, const QByteArray& data) override; + void remove(uint64_t offset, uint64_t length) override; + QByteArray read(uint64_t offset, uint64_t length) override; + void read(QIODevice* device) override; + void write(QIODevice* device) override; private: QByteArray m_buffer; diff --git a/dwarfexplorer/QHexView/document/buffer/qmemoryrefbuffer.h b/dwarfexplorer/QHexView/document/buffer/qmemoryrefbuffer.h index 06fdc62..7c727a6 100644 --- a/dwarfexplorer/QHexView/document/buffer/qmemoryrefbuffer.h +++ b/dwarfexplorer/QHexView/document/buffer/qmemoryrefbuffer.h @@ -9,13 +9,13 @@ class QMemoryRefBuffer : public QHexBuffer Q_OBJECT public: - explicit QMemoryRefBuffer(QObject *parent = nullptr); - int length() const override; - void insert(int, const QByteArray&) override; - void remove(int offset, int length) override; - QByteArray read(int offset, int length) override; - void read(QIODevice* device) override; - void write(QIODevice* device) override; + explicit QMemoryRefBuffer(QObject *parent = nullptr); + uint64_t length() const override; + void insert(uint64_t, const QByteArray&) override; + void remove(uint64_t offset, uint64_t length) override; + QByteArray read(uint64_t offset, uint64_t length) override; + void read(QIODevice* device) override; + void write(QIODevice* device) override; private: QBuffer* m_buffer; diff --git a/dwarfexplorer/dfstructure_window.cpp b/dwarfexplorer/dfstructure_window.cpp index 08f1a74..775f756 100644 --- a/dwarfexplorer/dfstructure_window.cpp +++ b/dwarfexplorer/dfstructure_window.cpp @@ -5,12 +5,15 @@ #include "hexviewer_window.h" #include "QHexView/document/buffer/qmemorybuffer.h" #include "MainWindow.h" +#include using namespace rdf; extern void fill_globals(rdf::Node* p_node_parent); extern std::string to_hex(uint64_t p_dec); + + // //--------------------------------------------------------------------------------------- // @@ -20,8 +23,12 @@ DFStructure_Window::DFStructure_Window(QWidget *parent) : , m_outdated(false) { ui->setupUi(this); + + MainWindow *mw = dynamic_cast(parent); + bool ok = QObject::connect(mw, &MainWindow::resumed_signal, this, &DFStructure_Window::on_MainWindow_resumed); } + // //--------------------------------------------------------------------------------------- // @@ -50,10 +57,6 @@ void DFStructure_Window::set_outdated() QTreeView* treeview = ui->treeView; DF_Model* model = dynamic_cast(treeview->model()); model->set_outdated(); - - QString title = this->windowTitle(); - QString new_title = "OUTDATED - " + title; - this->setWindowTitle(new_title); } // @@ -72,7 +75,7 @@ void DFStructure_Window::on_actionOpen_in_new_window_triggered() DFStructure_Window* new_window = new DFStructure_Window(main_window); // Add the window to the list of child windows - main_window->add_child_window(new_window); + //main_window->add_child_window(new_window); // Get the selected node index QTreeView* l_treeview = ui->treeView; @@ -173,17 +176,14 @@ void DFStructure_Window::on_actionOpen_in_hex_viewer_triggered() // Get the selected node rdf::NodeBase* node = dynamic_cast(model->nodeFromIndex(selected_node)); - auto the_data = reinterpret_cast(node->m_address); - QHexDocument* document = QHexDocument::fromMemory(the_data, 1024); - QHexView* hexview = new QHexView(); - hexview->setDocument(document); - - document->setBaseAddress(node->m_address); - hexview->setReadOnly(true); + uint64_t the_address = node->m_address; + char* the_data = reinterpret_cast(node->m_address); + std::size_t the_size = std::min(std::size_t(4096), size_of_DF_Type(node->m_df_type)); + the_size = std::max(std::size_t(4096), the_size); - // window title - auto the_number = QString::fromStdString(to_hex(node->m_address)); - hexview->setWindowTitle("Memory viewer - " + the_number); + // Create the window and show it + MainWindow *mw = dynamic_cast(parent()); + auto hexview = new QHexViewer_Window(mw, the_address, the_data, the_size); hexview->show(); } @@ -208,29 +208,31 @@ void DFStructure_Window::on_actionOpenPointer_in_hex_viewer_triggered() // Get the selected node rdf::NodeBase *node_base = model->nodeFromIndex(selected_node); + // Get the address and the size of the data to be visualized uint64_t *pointer_address = reinterpret_cast(node_base->m_address); - uint64_t item_address = *pointer_address; - - auto the_data = reinterpret_cast(item_address); - auto the_size = std::min(std::size_t(4096), size_of_DF_Type(node_base->m_df_type)); + uint64_t the_address = *pointer_address; + char *the_data = reinterpret_cast(the_address); + std::size_t the_size = std::min(std::size_t(4096), size_of_DF_Type(node_base->m_df_type)); the_size = std::max(std::size_t(4096), the_size); - QHexDocument* document = QHexDocument::fromMemory(the_data, the_size); - document->setBaseAddress(item_address); - - QHexView *hexview = new QHexView(); - hexview->setDocument(document); - hexview->setReadOnly(true); - // Window tittle - auto the_number = QString::fromStdString(to_hex(item_address)); - hexview->setWindowTitle("Memory viewer - " + the_number); + // Create the window and show it + MainWindow* mw = dynamic_cast(parent()); + auto hexview = new QHexViewer_Window(mw, the_address, the_data, the_size); hexview->show(); } void DFStructure_Window::closeEvent (QCloseEvent* p_event) { // Do the thing - MainWindow* main_window = reinterpret_cast(parent()); - main_window->remove_child_window(this); p_event->accept(); } + +void DFStructure_Window::on_MainWindow_resumed() +{ + QString new_name = "OUTDATED -"; + auto name = this->windowTitle(); + new_name.append(name); + this->setWindowTitle(new_name); + + set_outdated(); +} diff --git a/dwarfexplorer/dfstructure_window.h b/dwarfexplorer/dfstructure_window.h index 4797e60..52dc12c 100644 --- a/dwarfexplorer/dfstructure_window.h +++ b/dwarfexplorer/dfstructure_window.h @@ -24,6 +24,8 @@ private Q_SLOTS: void on_actionOpen_in_new_window_triggered(); void on_actionOpen_in_hex_viewer_triggered(); void on_actionOpenPointer_in_hex_viewer_triggered(); +public slots: + void on_MainWindow_resumed(); protected: void closeEvent(QCloseEvent* p_close_event); private: diff --git a/dwarfexplorer/hexviewer_window.cpp b/dwarfexplorer/hexviewer_window.cpp index e6c3756..d4caf8b 100644 --- a/dwarfexplorer/hexviewer_window.cpp +++ b/dwarfexplorer/hexviewer_window.cpp @@ -1,13 +1,18 @@ #include "hexviewer_window.h" #include "df_model.h" #include "node.h" +#include "MainWindow.h" +#include "QHexView/qhexview.h" +#include "QHexView/document/buffer/qmemorybuffer.h" using namespace rdf; +extern std::string to_hex(uint64_t p_dec); -QHexViewer_Window::QHexViewer_Window(QWidget *parent, Qt::WindowFlags flags): - QMainWindow(parent, flags) +QHexViewer_Window::QHexViewer_Window(QWidget *parent, uint64_t p_address, char* p_data, std::size_t p_size) : + QMainWindow(parent) { + QToolBar *ptb = addToolBar("File"); // QAction *pactOpen = ptb -> addAction("Open..."); @@ -17,17 +22,40 @@ QHexViewer_Window::QHexViewer_Window(QWidget *parent, Qt::WindowFlags flags): // QMenu *pmenu = menuBar() -> addMenu("&File"); // pmenu -> addAction(pactOpen); // addAction (pactOpen); -// pmenu -> addAction("Go to offset...", this, SLOT(slotToOffset())); +// pmenu -> addAction("Go to offset...", this, SLOT(slotToOffset())); // pmenu -> addAction("About...", this, SLOT(slotAbout())); // pmenu -> addAction("Exit", this, SLOT(close())); + QHexDocument *document = QHexDocument::fromMemory(p_data, p_size); + document->setBaseAddress(p_address); + m_hexview = new QHexView(this); + m_hexview->setDocument(document); + m_hexview->setReadOnly(true); + setCentralWidget(m_hexview); -// readCustomData(); + // Window tittle + auto the_number = QString::fromStdString(to_hex(p_address)); + this->setWindowTitle("Memory viewer - " + the_number); + + MainWindow *mw = dynamic_cast(parent); + bool ok = QObject::connect(mw, &MainWindow::resumed_signal, this, &QHexViewer_Window::on_MainWindow_resumed); + + // readCustomData(); } -QHexView* QHexViewer_Window::get_hexview() +QHexView *QHexViewer_Window::get_hexview() { return m_hexview; } + +void QHexViewer_Window::on_MainWindow_resumed() +{ + QString new_name = "OUTDATED -"; + auto name = this->windowTitle(); + new_name.append(name); + this->setWindowTitle(new_name); + + //set_outdated(); +} \ No newline at end of file diff --git a/dwarfexplorer/hexviewer_window.h b/dwarfexplorer/hexviewer_window.h index 10db979..3f01a16 100644 --- a/dwarfexplorer/hexviewer_window.h +++ b/dwarfexplorer/hexviewer_window.h @@ -9,13 +9,18 @@ class QHexViewer_Window : public QMainWindow Q_OBJECT public: - explicit QHexViewer_Window(QWidget *parent = 0, Qt::WindowFlags flags = 0); - //~QHexViewer_Window(); - QHexView* get_hexview(); + QHexViewer_Window(QWidget *parent, uint64_t p_address, char *p_data, std::size_t p_size); + ~QHexViewer_Window() + { + delete m_hexview; + m_hexview = nullptr; + } + + QHexView *get_hexview(); + protected: QHexView* m_hexview; private Q_SLOTS: - + void on_MainWindow_resumed(); }; - #endif // HEXVIEWER_WINDOW_H \ No newline at end of file diff --git a/dwarfexplorer/node.cpp b/dwarfexplorer/node.cpp index 8f67b02..4090ad6 100644 --- a/dwarfexplorer/node.cpp +++ b/dwarfexplorer/node.cpp @@ -21,11 +21,16 @@ std::string NodeBase::path() result.append(this->node_path_name()); } else - for (auto i = path.size() - 1; i >= 0; i--) + { + int i = path.size() - 1; + while (i >= 0) { result.append("."); - result.append(path[i]->node_path_name()); + NodeBase* node = path[i--]; + if (node != nullptr) + result.append(node->node_path_name()); } + } return result; } diff --git a/dwarfexplorer/resources/Breezeicons-actions-22-media-playback-pause.png b/dwarfexplorer/resources/Breezeicons-actions-22-media-playback-pause.png new file mode 100644 index 0000000..eab55fb Binary files /dev/null and b/dwarfexplorer/resources/Breezeicons-actions-22-media-playback-pause.png differ diff --git a/dwarfexplorer/resources/Breezeicons-actions-22-media-playback-start.png b/dwarfexplorer/resources/Breezeicons-actions-22-media-playback-start.png new file mode 100644 index 0000000..65f7bf7 Binary files /dev/null and b/dwarfexplorer/resources/Breezeicons-actions-22-media-playback-start.png differ diff --git a/dwarfexplorer/resources/resources.qrc b/dwarfexplorer/resources/resources.qrc index f29e5d7..9b39839 100644 --- a/dwarfexplorer/resources/resources.qrc +++ b/dwarfexplorer/resources/resources.qrc @@ -13,5 +13,7 @@ stripes.png t_small.png t2_small.png + Breezeicons-actions-22-media-playback-pause.png + Breezeicons-actions-22-media-playback-start.png diff --git a/images/1.gif b/images/1.gif new file mode 100644 index 0000000..d550a80 Binary files /dev/null and b/images/1.gif differ diff --git a/images/2.gif b/images/2.gif new file mode 100644 index 0000000..f52a6ee Binary files /dev/null and b/images/2.gif differ diff --git a/images/3.gif b/images/3.gif new file mode 100644 index 0000000..6da84ad Binary files /dev/null and b/images/3.gif differ diff --git a/images/4.gif b/images/4.gif new file mode 100644 index 0000000..e49dfe1 Binary files /dev/null and b/images/4.gif differ diff --git a/images/5.gif b/images/5.gif new file mode 100644 index 0000000..da4aadb Binary files /dev/null and b/images/5.gif differ diff --git a/images/6.gif b/images/6.gif new file mode 100644 index 0000000..c503707 Binary files /dev/null and b/images/6.gif differ diff --git a/images/dwarf_explorer.png b/images/dwarf_explorer.png new file mode 100644 index 0000000..da62469 Binary files /dev/null and b/images/dwarf_explorer.png differ