├── README.md ├── archive_widget.cmake ├── LICENSE ├── archive_widget.pri ├── dialogshowtext.ui ├── dialogshowtext.h ├── dialogunpackfile.h ├── dialogarchive.ui ├── dialogshowimage.ui ├── dialogshowtext.cpp ├── unpackfileprocess.h ├── dialogunpackfile.cpp ├── dialogarchive.h ├── dialogshowimage.h ├── xarchivewidget.ui ├── dialogcreateviewmodel.h ├── createviewmodelprocess.h ├── dialogarchive.cpp ├── xarchivewidget.h ├── unpackfileprocess.cpp ├── dialogcreateviewmodel.cpp ├── archive_widget.h ├── archive_widget.ui ├── dialogshowimage.cpp ├── createviewmodelprocess.cpp ├── xarchivewidget.cpp └── archive_widget.cpp /README.md: -------------------------------------------------------------------------------- 1 | Archive widget for archives: 2 | 3 | * ZIP 4 | * MACHOFAT 5 | -------------------------------------------------------------------------------- /archive_widget.cmake: -------------------------------------------------------------------------------- 1 | include_directories(${CMAKE_CURRENT_LIST_DIR}) 2 | 3 | include(${CMAKE_CURRENT_LIST_DIR}/../FormatWidgets/allformatwidgets.cmake) 4 | include(${CMAKE_CURRENT_LIST_DIR}/../XArchive/xarchives.cmake) 5 | include(${CMAKE_CURRENT_LIST_DIR}/../XShortcuts/xshortcuts.cmake) 6 | 7 | set(ARCHIVE_WIDGET_SOURCES 8 | ${ALLFORMATWIDGETS_SOURCES} 9 | ${XARCHIVES_SOURCES} 10 | ${XSHORTCUTS_SOURCES} 11 | ${CMAKE_CURRENT_LIST_DIR}/archive_widget.cmake 12 | ${CMAKE_CURRENT_LIST_DIR}/archive_widget.cpp 13 | ${CMAKE_CURRENT_LIST_DIR}/archive_widget.ui 14 | ${CMAKE_CURRENT_LIST_DIR}/createviewmodelprocess.cpp 15 | ${CMAKE_CURRENT_LIST_DIR}/dialogarchive.cpp 16 | ${CMAKE_CURRENT_LIST_DIR}/dialogarchive.ui 17 | ${CMAKE_CURRENT_LIST_DIR}/dialogcreateviewmodel.cpp 18 | ${CMAKE_CURRENT_LIST_DIR}/dialogshowimage.cpp 19 | ${CMAKE_CURRENT_LIST_DIR}/dialogshowimage.ui 20 | ${CMAKE_CURRENT_LIST_DIR}/dialogunpackfile.cpp 21 | ${CMAKE_CURRENT_LIST_DIR}/unpackfileprocess.cpp 22 | ${CMAKE_CURRENT_LIST_DIR}/xarchivewidget.cpp 23 | ${CMAKE_CURRENT_LIST_DIR}/xarchivewidget.ui 24 | ) 25 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2020-2025 hors 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /archive_widget.pri: -------------------------------------------------------------------------------- 1 | QT += concurrent 2 | 3 | INCLUDEPATH += $$PWD 4 | DEPENDPATH += $$PWD 5 | 6 | !contains(XCONFIG, use_dex) { 7 | XCONFIG += use_dex 8 | } 9 | 10 | !contains(XCONFIG, use_pdf) { 11 | XCONFIG += use_pdf 12 | } 13 | 14 | !contains(XCONFIG, use_archive) { 15 | XCONFIG += use_archive 16 | } 17 | 18 | HEADERS += \ 19 | $$PWD/archive_widget.h \ 20 | $$PWD/createviewmodelprocess.h \ 21 | $$PWD/dialogarchive.h \ 22 | $$PWD/dialogcreateviewmodel.h \ 23 | $$PWD/dialogshowimage.h \ 24 | $$PWD/dialogunpackfile.h \ 25 | $$PWD/unpackfileprocess.h \ 26 | $$PWD/xarchivewidget.h 27 | 28 | SOURCES += \ 29 | $$PWD/archive_widget.cpp \ 30 | $$PWD/createviewmodelprocess.cpp \ 31 | $$PWD/dialogarchive.cpp \ 32 | $$PWD/dialogcreateviewmodel.cpp \ 33 | $$PWD/dialogshowimage.cpp \ 34 | $$PWD/dialogunpackfile.cpp \ 35 | $$PWD/unpackfileprocess.cpp \ 36 | $$PWD/xarchivewidget.cpp 37 | 38 | FORMS += \ 39 | $$PWD/archive_widget.ui \ 40 | $$PWD/dialogarchive.ui \ 41 | $$PWD/dialogshowimage.ui \ 42 | $$PWD/xarchivewidget.ui 43 | 44 | !contains(XCONFIG, allformatwidgets) { 45 | XCONFIG += allformatwidgets 46 | include($$PWD/../FormatWidgets/allformatwidgets.pri) 47 | } 48 | 49 | !contains(XCONFIG, xarchives) { 50 | XCONFIG += xarchives 51 | include($$PWD/../XArchive/xarchives.pri) 52 | } 53 | 54 | DISTFILES += \ 55 | $$PWD/LICENSE \ 56 | $$PWD/README.md \ 57 | $$PWD/archive_widget.cmake 58 | 59 | -------------------------------------------------------------------------------- /dialogshowtext.ui: -------------------------------------------------------------------------------- 1 | 2 | 3 | DialogShowText 4 | 5 | 6 | Qt::ApplicationModal 7 | 8 | 9 | 10 | 0 11 | 0 12 | 716 13 | 480 14 | 15 | 16 | 17 | Text 18 | 19 | 20 | true 21 | 22 | 23 | 24 | 25 | 26 | QPlainTextEdit::NoWrap 27 | 28 | 29 | true 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | Qt::Horizontal 39 | 40 | 41 | 42 | 40 43 | 20 44 | 45 | 46 | 47 | 48 | 49 | 50 | 51 | Close 52 | 53 | 54 | 55 | 56 | 57 | 58 | 59 | 60 | 61 | 62 | -------------------------------------------------------------------------------- /dialogshowtext.h: -------------------------------------------------------------------------------- 1 | /* Copyright (c) 2020-2022 hors 2 | * 3 | * Permission is hereby granted, free of charge, to any person obtaining a copy 4 | * of this software and associated documentation files (the "Software"), to deal 5 | * in the Software without restriction, including without limitation the rights 6 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 7 | * copies of the Software, and to permit persons to whom the Software is 8 | * furnished to do so, subject to the following conditions: 9 | * 10 | * The above copyright notice and this permission notice shall be included in all 11 | * copies or substantial portions of the Software. 12 | * 13 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 14 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 15 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 16 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 17 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 18 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 19 | * SOFTWARE. 20 | */ 21 | #ifndef DIALOGSHOWTEXT_H 22 | #define DIALOGSHOWTEXT_H 23 | 24 | #include 25 | #include 26 | #include 27 | 28 | namespace Ui { 29 | class DialogShowText; 30 | } 31 | 32 | class DialogShowText : public QDialog 33 | { 34 | Q_OBJECT 35 | 36 | public: 37 | enum TYPE 38 | { 39 | TYPE_UNKNOWN=0, 40 | TYPE_FILECONTENT, 41 | TYPE_PLAINTEXT 42 | }; 43 | 44 | explicit DialogShowText(QWidget *pParent,QString sTitle); 45 | void setData(QString sString,TYPE type); 46 | ~DialogShowText(); 47 | 48 | private slots: 49 | void on_pushButtonClose_clicked(); 50 | 51 | private: 52 | Ui::DialogShowText *ui; 53 | }; 54 | 55 | #endif // DIALOGSHOWTEXT_H 56 | -------------------------------------------------------------------------------- /dialogunpackfile.h: -------------------------------------------------------------------------------- 1 | /* Copyright (c) 2020-2025 hors 2 | * 3 | * Permission is hereby granted, free of charge, to any person obtaining a copy 4 | * of this software and associated documentation files (the "Software"), to deal 5 | * in the Software without restriction, including without limitation the rights 6 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 7 | * copies of the Software, and to permit persons to whom the Software is 8 | * furnished to do so, subject to the following conditions: 9 | * 10 | * The above copyright notice and this permission notice shall be included in 11 | * all copies or substantial portions of the Software. 12 | * 13 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 14 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 15 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 16 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 17 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 18 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 19 | * SOFTWARE. 20 | */ 21 | #ifndef DIALOGUNPACKFILE_H 22 | #define DIALOGUNPACKFILE_H 23 | 24 | #include "unpackfileprocess.h" 25 | #include "xdialogprocess.h" 26 | 27 | class DialogUnpackFile : public XDialogProcess { 28 | Q_OBJECT 29 | 30 | public: 31 | explicit DialogUnpackFile(QWidget *pParent = nullptr); 32 | 33 | void setData(const QString &sFileName, XArchive::RECORD *pRecord, const QString &sResultFileName); 34 | void setData(const QString &sFileName, const QString &sResultFileFolder); 35 | void setData(QIODevice *pDevice, XArchive::RECORD *pRecord, const QString &sResultFileName); 36 | void setData(QIODevice *pDevice, const QString &sResultFileFolder); 37 | 38 | private: 39 | UnpackFileProcess *m_pUnpackFileProcess; 40 | }; 41 | 42 | #endif // DIALOGUNPACKFILE_H 43 | -------------------------------------------------------------------------------- /dialogarchive.ui: -------------------------------------------------------------------------------- 1 | 2 | 3 | DialogArchive 4 | 5 | 6 | 7 | 0 8 | 0 9 | 592 10 | 283 11 | 12 | 13 | 14 | Archive 15 | 16 | 17 | 18 | 19 | 20 | 21 | 0 22 | 0 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | Qt::Horizontal 33 | 34 | 35 | 36 | 40 37 | 20 38 | 39 | 40 | 41 | 42 | 43 | 44 | 45 | Open 46 | 47 | 48 | 49 | 50 | 51 | 52 | Close 53 | 54 | 55 | 56 | 57 | 58 | 59 | 60 | 61 | 62 | Archive_widget 63 | QWidget 64 |
archive_widget.h
65 | 1 66 |
67 |
68 | 69 | 70 |
71 | -------------------------------------------------------------------------------- /dialogshowimage.ui: -------------------------------------------------------------------------------- 1 | 2 | 3 | DialogShowImage 4 | 5 | 6 | Qt::ApplicationModal 7 | 8 | 9 | 10 | 0 11 | 0 12 | 400 13 | 300 14 | 15 | 16 | 17 | Image 18 | 19 | 20 | true 21 | 22 | 23 | 24 | 25 | 26 | 27 | 0 28 | 0 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | Image information 40 | 41 | 42 | Qt::AlignCenter 43 | 44 | 45 | 46 | 47 | 48 | 49 | 50 | 51 | Qt::Horizontal 52 | 53 | 54 | 55 | 40 56 | 20 57 | 58 | 59 | 60 | 61 | 62 | 63 | 64 | Close 65 | 66 | 67 | 68 | 69 | 70 | 71 | 72 | 73 | 74 | 75 | -------------------------------------------------------------------------------- /dialogshowtext.cpp: -------------------------------------------------------------------------------- 1 | /* Copyright (c) 2020-2022 hors 2 | * 3 | * Permission is hereby granted, free of charge, to any person obtaining a copy 4 | * of this software and associated documentation files (the "Software"), to deal 5 | * in the Software without restriction, including without limitation the rights 6 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 7 | * copies of the Software, and to permit persons to whom the Software is 8 | * furnished to do so, subject to the following conditions: 9 | * 10 | * The above copyright notice and this permission notice shall be included in all 11 | * copies or substantial portions of the Software. 12 | * 13 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 14 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 15 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 16 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 17 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 18 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 19 | * SOFTWARE. 20 | */ 21 | #include "dialogshowtext.h" 22 | #include "ui_dialogshowtext.h" 23 | 24 | DialogShowText::DialogShowText(QWidget *pParent,QString sTitle) : 25 | QDialog(pParent), 26 | ui(new Ui::DialogShowText) 27 | { 28 | ui->setupUi(this); 29 | 30 | setWindowFlags(Qt::Window); 31 | setWindowTitle(sTitle); 32 | } 33 | 34 | void DialogShowText::setData(QString sString,DialogShowText::TYPE type) 35 | { 36 | if(type==TYPE_FILECONTENT) 37 | { 38 | QFile file(sString); 39 | 40 | if(file.open(QIODevice::ReadOnly|QIODevice::Text)) 41 | { 42 | QTextStream stream(&file); 43 | 44 | ui->plainTextEdit->setPlainText(stream.readAll()); 45 | } 46 | 47 | file.close(); 48 | } 49 | else if(type==TYPE_PLAINTEXT) 50 | { 51 | ui->plainTextEdit->setPlainText(sString); 52 | } 53 | } 54 | 55 | DialogShowText::~DialogShowText() 56 | { 57 | delete ui; 58 | } 59 | 60 | void DialogShowText::on_pushButtonClose_clicked() 61 | { 62 | this->close(); 63 | } 64 | -------------------------------------------------------------------------------- /unpackfileprocess.h: -------------------------------------------------------------------------------- 1 | /* Copyright (c) 2020-2025 hors 2 | * 3 | * Permission is hereby granted, free of charge, to any person obtaining a copy 4 | * of this software and associated documentation files (the "Software"), to deal 5 | * in the Software without restriction, including without limitation the rights 6 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 7 | * copies of the Software, and to permit persons to whom the Software is 8 | * furnished to do so, subject to the following conditions: 9 | * 10 | * The above copyright notice and this permission notice shall be included in 11 | * all copies or substantial portions of the Software. 12 | * 13 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 14 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 15 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 16 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 17 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 18 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 19 | * SOFTWARE. 20 | */ 21 | #ifndef UNPACKFILEPROCESS_H 22 | #define UNPACKFILEPROCESS_H 23 | 24 | #include "xarchives.h" 25 | #include "xthreadobject.h" 26 | 27 | class UnpackFileProcess : public XThreadObject { 28 | Q_OBJECT 29 | 30 | public: 31 | explicit UnpackFileProcess(QObject *pParent = nullptr); 32 | 33 | void setData(const QString &sFileName, XArchive::RECORD *pRecord, const QString &sResultFileName, XBinary::PDSTRUCT *pPdStruct); 34 | void setData(const QString &sFileName, const QString &sResultFileFolder, XBinary::PDSTRUCT *pPdStruct); 35 | void setData(QIODevice *pDevice, XArchive::RECORD *pRecord, const QString &sResultFileName, XBinary::PDSTRUCT *pPdStruct); 36 | void setData(QIODevice *pDevice, const QString &sResultFileFolder, XBinary::PDSTRUCT *pPdStruct); 37 | 38 | virtual void process() override; 39 | 40 | private: 41 | QString m_sFileName; 42 | QIODevice *m_pDevice; 43 | XArchive::RECORD *m_pRecord; 44 | QString m_sResultFileName; 45 | QString m_sResultFileFolder; 46 | XBinary::PDSTRUCT *m_pPdStruct; 47 | }; 48 | 49 | #endif // UNPACKFILEPROCESS_H 50 | -------------------------------------------------------------------------------- /dialogunpackfile.cpp: -------------------------------------------------------------------------------- 1 | /* Copyright (c) 2020-2025 hors 2 | * 3 | * Permission is hereby granted, free of charge, to any person obtaining a copy 4 | * of this software and associated documentation files (the "Software"), to deal 5 | * in the Software without restriction, including without limitation the rights 6 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 7 | * copies of the Software, and to permit persons to whom the Software is 8 | * furnished to do so, subject to the following conditions: 9 | * 10 | * The above copyright notice and this permission notice shall be included in 11 | * all copies or substantial portions of the Software. 12 | * 13 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 14 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 15 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 16 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 17 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 18 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 19 | * SOFTWARE. 20 | */ 21 | #include "dialogunpackfile.h" 22 | 23 | DialogUnpackFile::DialogUnpackFile(QWidget *pParent) : XDialogProcess(pParent, new UnpackFileProcess) 24 | { 25 | m_pUnpackFileProcess = static_cast(getThreadObject()); 26 | } 27 | 28 | void DialogUnpackFile::setData(const QString &sFileName, XArchive::RECORD *pRecord, const QString &sResultFileName) 29 | { 30 | m_pUnpackFileProcess->setData(sFileName, pRecord, sResultFileName, getPdStruct()); 31 | start(); 32 | } 33 | 34 | void DialogUnpackFile::setData(const QString &sFileName, const QString &sResultFileFolder) 35 | { 36 | m_pUnpackFileProcess->setData(sFileName, sResultFileFolder, getPdStruct()); 37 | start(); 38 | } 39 | 40 | void DialogUnpackFile::setData(QIODevice *pDevice, XArchive::RECORD *pRecord, const QString &sResultFileName) 41 | { 42 | m_pUnpackFileProcess->setData(pDevice, pRecord, sResultFileName, getPdStruct()); 43 | start(); 44 | } 45 | 46 | void DialogUnpackFile::setData(QIODevice *pDevice, const QString &sResultFileFolder) 47 | { 48 | m_pUnpackFileProcess->setData(pDevice, sResultFileFolder, getPdStruct()); 49 | start(); 50 | } 51 | -------------------------------------------------------------------------------- /dialogarchive.h: -------------------------------------------------------------------------------- 1 | /* Copyright (c) 2020-2025 hors 2 | * 3 | * Permission is hereby granted, free of charge, to any person obtaining a copy 4 | * of this software and associated documentation files (the "Software"), to deal 5 | * in the Software without restriction, including without limitation the rights 6 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 7 | * copies of the Software, and to permit persons to whom the Software is 8 | * furnished to do so, subject to the following conditions: 9 | * 10 | * The above copyright notice and this permission notice shall be included in 11 | * all copies or substantial portions of the Software. 12 | * 13 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 14 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 15 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 16 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 17 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 18 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 19 | * SOFTWARE. 20 | */ 21 | #ifndef DIALOGARCHIVE_H 22 | #define DIALOGARCHIVE_H 23 | 24 | #include 25 | 26 | #include "archive_widget.h" 27 | 28 | // TODO DialogShortcuts !!! 29 | namespace Ui { 30 | class DialogArchive; 31 | } 32 | 33 | class DialogArchive : public XShortcutsDialog { 34 | Q_OBJECT 35 | 36 | public: 37 | explicit DialogArchive(QWidget *pParent = nullptr); 38 | ~DialogArchive(); 39 | 40 | virtual void adjustView(); 41 | 42 | void setFileName(const QString &sFileName, XBinary::FT fileType, const FW_DEF::OPTIONS &options, const QSet &stAvailableFileTypes); 43 | void setDevice(QIODevice *pDevice, XBinary::FT fileType, const FW_DEF::OPTIONS &options, QSet stAvailableFileTypes); 44 | void setDirectory(const QString &sDirectoryName, const FW_DEF::OPTIONS &options, QSet stAvailableFileTypes); 45 | void setGlobal(XShortcuts *pShortcuts, XOptions *pXOptions); 46 | QString getCurrentRecordFileName(); 47 | 48 | private slots: 49 | void on_pushButtonClose_clicked(); 50 | void on_pushButtonOpen_clicked(); 51 | 52 | protected: 53 | virtual void registerShortcuts(bool bState); 54 | 55 | private: 56 | Ui::DialogArchive *ui; 57 | QString m_sCurrentRecordFileName; 58 | FW_DEF::OPTIONS m_options; 59 | }; 60 | 61 | #endif // DIALOGARCHIVE_H 62 | -------------------------------------------------------------------------------- /dialogshowimage.h: -------------------------------------------------------------------------------- 1 | /* Copyright (c) 2020-2025 hors 2 | * 3 | * Permission is hereby granted, free of charge, to any person obtaining a copy 4 | * of this software and associated documentation files (the "Software"), to deal 5 | * in the Software without restriction, including without limitation the rights 6 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 7 | * copies of the Software, and to permit persons to whom the Software is 8 | * furnished to do so, subject to the following conditions: 9 | * 10 | * The above copyright notice and this permission notice shall be included in 11 | * all copies or substantial portions of the Software. 12 | * 13 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 14 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 15 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 16 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 17 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 18 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 19 | * SOFTWARE. 20 | */ 21 | #ifndef DIALOGSHOWIMAGE_H 22 | #define DIALOGSHOWIMAGE_H 23 | 24 | #include "xshortcutsdialog.h" 25 | #include 26 | 27 | namespace Ui { 28 | class DialogShowImage; 29 | } 30 | 31 | // TODO move to FormatDialogs 32 | class DialogShowImage : public XShortcutsDialog { 33 | Q_OBJECT 34 | 35 | public: 36 | explicit DialogShowImage(QWidget *pParent, const QString &sFileName, const QString &sTitle); 37 | ~DialogShowImage(); 38 | 39 | virtual void adjustView(); 40 | 41 | private slots: 42 | void on_pushButtonClose_clicked(); 43 | 44 | private: 45 | void updateImageDisplay(); 46 | void setZoomFactor(qreal factor); 47 | void zoomIn(); 48 | void zoomOut(); 49 | void fitToWindow(); 50 | void actualSize(); 51 | void copyToClipboard(); 52 | void saveAs(); 53 | void updateImageInfo(); 54 | Ui::DialogShowImage *ui; 55 | QPixmap m_originalPixmap; 56 | QPixmap m_currentPixmap; 57 | qreal m_zoomFactor; 58 | bool m_fitToWindow; 59 | QMenu *m_contextMenu; 60 | 61 | protected: 62 | virtual void registerShortcuts(bool bState); 63 | void contextMenuEvent(QContextMenuEvent *event) override; 64 | void wheelEvent(QWheelEvent *event) override; 65 | }; 66 | 67 | #endif // DIALOGSHOWIMAGE_H 68 | -------------------------------------------------------------------------------- /xarchivewidget.ui: -------------------------------------------------------------------------------- 1 | 2 | 3 | XArchiveWidget 4 | 5 | 6 | 7 | 0 8 | 0 9 | 600 10 | 400 11 | 12 | 13 | 14 | Archive 15 | 16 | 17 | 18 | 0 19 | 20 | 21 | 0 22 | 23 | 24 | 0 25 | 26 | 27 | 0 28 | 29 | 30 | 31 | 32 | Filter 33 | 34 | 35 | 36 | 2 37 | 38 | 39 | 2 40 | 41 | 42 | 2 43 | 44 | 45 | 2 46 | 47 | 48 | 49 | 50 | 51 | 52 | 53 | 54 | 55 | 56 | Qt::CustomContextMenu 57 | 58 | 59 | QAbstractItemView::NoEditTriggers 60 | 61 | 62 | QAbstractItemView::SingleSelection 63 | 64 | 65 | QAbstractItemView::SelectRows 66 | 67 | 68 | false 69 | 70 | 71 | 20 72 | 73 | 74 | 20 75 | 76 | 77 | 78 | 79 | 80 | 81 | 82 | 83 | -------------------------------------------------------------------------------- /dialogcreateviewmodel.h: -------------------------------------------------------------------------------- 1 | /* Copyright (c) 2019-2025 hors 2 | * 3 | * Permission is hereby granted, free of charge, to any person obtaining a copy 4 | * of this software and associated documentation files (the "Software"), to deal 5 | * in the Software without restriction, including without limitation the rights 6 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 7 | * copies of the Software, and to permit persons to whom the Software is 8 | * furnished to do so, subject to the following conditions: 9 | * 10 | * The above copyright notice and this permission notice shall be included in 11 | * all copies or substantial portions of the Software. 12 | * 13 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 14 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 15 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 16 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 17 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 18 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 19 | * SOFTWARE. 20 | */ 21 | #ifndef DIALOGCREATEVIEWMODEL_H 22 | #define DIALOGCREATEVIEWMODEL_H 23 | 24 | #include 25 | #include 26 | #include 27 | #include 28 | #include 29 | 30 | #include "createviewmodelprocess.h" 31 | #include "xdialogprocess.h" 32 | 33 | namespace Ui { 34 | class DialogCreateViewModel; 35 | } 36 | 37 | class DialogCreateViewModel : public XDialogProcess { 38 | Q_OBJECT 39 | 40 | public: 41 | explicit DialogCreateViewModel(QWidget *pParent = nullptr); 42 | ~DialogCreateViewModel(); 43 | 44 | void setData(CreateViewModelProcess::TYPE type, const QString &sName, XBinary::FT fileType, QList *pListArchiveRecords, 45 | QStandardItemModel **ppTreeModel, QStandardItemModel **ppTableModel, const QSet &stFilterFileTypes, 46 | QList *pListViewRecords); 47 | bool isRunning() const 48 | { 49 | return m_bIsRunning; 50 | } 51 | 52 | private slots: 53 | void onCompleted(qint64 nElapsed); 54 | void onProgressValueChanged(qint32 nValue); 55 | void onProgressMessageChanged(const QString &sText); 56 | void onErrorMessage(const QString &sText); 57 | 58 | private: 59 | QScopedPointer m_pCreateViewModelProcess; 60 | QScopedPointer m_pThread; 61 | bool m_bIsRunning; 62 | }; 63 | 64 | #endif // DIALOGCREATEVIEWMODEL_H 65 | -------------------------------------------------------------------------------- /createviewmodelprocess.h: -------------------------------------------------------------------------------- 1 | /* Copyright (c) 2020-2025 hors 2 | * 3 | * Permission is hereby granted, free of charge, to any person obtaining a copy 4 | * of this software and associated documentation files (the "Software"), to deal 5 | * in the Software without restriction, including without limitation the rights 6 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 7 | * copies of the Software, and to permit persons to whom the Software is 8 | * furnished to do so, subject to the following conditions: 9 | * 10 | * The above copyright notice and this permission notice shall be included in 11 | * all copies or substantial portions of the Software. 12 | * 13 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 14 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 15 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 16 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 17 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 18 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 19 | * SOFTWARE. 20 | */ 21 | #ifndef CREATEVIEWMODELPROCESS_H 22 | #define CREATEVIEWMODELPROCESS_H 23 | 24 | #include 25 | #include 26 | 27 | #include "xformats.h" 28 | 29 | class CreateViewModelProcess : public QObject { 30 | Q_OBJECT 31 | 32 | public: 33 | enum UR { 34 | UR_PATH = 0, 35 | UR_SIZE, 36 | UR_ISROOT, 37 | UR_FT 38 | }; 39 | 40 | enum TYPE { 41 | TYPE_UNKNOWN = 0, 42 | TYPE_FILE, 43 | TYPE_DIRECTORY 44 | }; 45 | 46 | struct RECORD { 47 | QString sRecordName; 48 | XBinary::FT ft; 49 | bool bIsVirtual; 50 | }; 51 | 52 | struct STATS { 53 | qint32 nTotal; 54 | qint32 nCurrent; 55 | QString sStatus; 56 | }; 57 | 58 | explicit CreateViewModelProcess(QObject *pParent = nullptr); 59 | 60 | void setData(CreateViewModelProcess::TYPE type, const QString &sName, XBinary::FT fileType, QList *pListArchiveRecords, 61 | QStandardItemModel **ppTreeModel, QStandardItemModel **ppTableModel, const QSet &stFilterFileTypes, QList *pListViewRecords, 62 | XBinary::PDSTRUCT *pPdStruct); 63 | 64 | signals: 65 | void errorMessage(const QString &sText); 66 | void completed(qint64 nElapsed); 67 | void progressValueChanged(qint32 nValue); 68 | void progressMessageChanged(const QString &sText); 69 | 70 | public slots: 71 | void process(); 72 | 73 | private: 74 | TYPE m_type; 75 | QString m_sName; 76 | XBinary::FT m_fileType; 77 | QList *m_pListArchiveRecords; 78 | QStandardItemModel **m_ppTreeModel; 79 | QStandardItemModel **m_ppTableModel; 80 | QSet m_stFilterFileTypes; 81 | QList *m_pListViewRecords; 82 | XBinary::PDSTRUCT *m_pPdStruct; 83 | }; 84 | 85 | #endif // CREATEVIEWMODELPROCESS_H 86 | -------------------------------------------------------------------------------- /dialogarchive.cpp: -------------------------------------------------------------------------------- 1 | /* Copyright (c) 2020-2025 hors 2 | * 3 | * Permission is hereby granted, free of charge, to any person obtaining a copy 4 | * of this software and associated documentation files (the "Software"), to deal 5 | * in the Software without restriction, including without limitation the rights 6 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 7 | * copies of the Software, and to permit persons to whom the Software is 8 | * furnished to do so, subject to the following conditions: 9 | * 10 | * The above copyright notice and this permission notice shall be included in 11 | * all copies or substantial portions of the Software. 12 | * 13 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 14 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 15 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 16 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 17 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 18 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 19 | * SOFTWARE. 20 | */ 21 | #include "dialogarchive.h" 22 | 23 | #include "ui_dialogarchive.h" 24 | 25 | DialogArchive::DialogArchive(QWidget *pParent) : XShortcutsDialog(pParent, true), ui(new Ui::DialogArchive) 26 | { 27 | ui->setupUi(this); 28 | 29 | m_options = {}; 30 | } 31 | 32 | DialogArchive::~DialogArchive() 33 | { 34 | delete ui; 35 | } 36 | 37 | void DialogArchive::adjustView() 38 | { 39 | } 40 | 41 | void DialogArchive::setFileName(const QString &sFileName, XBinary::FT fileType, const FW_DEF::OPTIONS &options, const QSet &stAvailableFileTypes) 42 | { 43 | if (options.sTitle != "") { 44 | setWindowTitle(options.sTitle); 45 | } 46 | 47 | m_options = options; 48 | ui->widget->setFileName(sFileName, fileType, options, stAvailableFileTypes); 49 | } 50 | 51 | void DialogArchive::setDevice(QIODevice *pDevice, XBinary::FT fileType, const FW_DEF::OPTIONS &options, QSet stAvailableFileTypes) 52 | { 53 | setFileName(XBinary::getDeviceFileName(pDevice), fileType, options, stAvailableFileTypes); 54 | } 55 | 56 | void DialogArchive::setDirectory(const QString &sDirectoryName, const FW_DEF::OPTIONS &options, QSet stAvailableFileTypes) 57 | { 58 | if (options.sTitle != "") { 59 | setWindowTitle(options.sTitle); 60 | } 61 | 62 | m_options = options; 63 | ui->widget->setDirectoryName(sDirectoryName, options, stAvailableFileTypes); 64 | } 65 | 66 | void DialogArchive::setGlobal(XShortcuts *pShortcuts, XOptions *pXOptions) 67 | { 68 | ui->widget->setGlobal(pShortcuts, pXOptions); 69 | } 70 | 71 | QString DialogArchive::getCurrentRecordFileName() 72 | { 73 | return m_sCurrentRecordFileName; 74 | } 75 | 76 | void DialogArchive::on_pushButtonClose_clicked() 77 | { 78 | reject(); 79 | } 80 | 81 | void DialogArchive::on_pushButtonOpen_clicked() 82 | { 83 | m_sCurrentRecordFileName = ui->widget->getCurrentRecordFileName(); 84 | 85 | if (!m_options.bNoWindowOpen) { 86 | ui->widget->openRecord(); 87 | } else { 88 | accept(); 89 | } 90 | } 91 | 92 | void DialogArchive::registerShortcuts(bool bState) 93 | { 94 | Q_UNUSED(bState) 95 | } 96 | -------------------------------------------------------------------------------- /xarchivewidget.h: -------------------------------------------------------------------------------- 1 | /* Copyright (c) 2020-2025 hors 2 | * 3 | * Permission is hereby granted, free of charge, to any person obtaining a copy 4 | * of this software and associated documentation files (the "Software"), to deal 5 | * in the Software without restriction, including without limitation the rights 6 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 7 | * copies of the Software, and to permit persons to whom the Software is 8 | * furnished to do so, subject to the following conditions: 9 | * 10 | * The above copyright notice and this permission notice shall be included in 11 | * all copies or substantial portions of the Software. 12 | * 13 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 14 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 15 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 16 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 17 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 18 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 19 | * SOFTWARE. 20 | */ 21 | #ifndef XARCHIVEWIDGET_H 22 | #define XARCHIVEWIDGET_H 23 | 24 | #include 25 | #include 26 | #include 27 | #include 28 | #include 29 | #include 30 | #include 31 | #include 32 | #include 33 | #include "xarchive.h" 34 | #include "xshortcutswidget.h" 35 | 36 | namespace Ui { 37 | class XArchiveWidget; 38 | } 39 | 40 | class XArchiveWidget : public XShortcutsWidget { 41 | Q_OBJECT 42 | 43 | enum ACTION { 44 | ACTION_HEX = 0, 45 | ACTION_STRINGS, 46 | ACTION_ENTROPY, 47 | ACTION_HASH, 48 | ACTION_COPYFILENAME, 49 | ACTION_DUMP 50 | }; 51 | 52 | public: 53 | explicit XArchiveWidget(QWidget *pParent = nullptr); 54 | ~XArchiveWidget(); 55 | 56 | void setData(XBinary::FT fileType, QIODevice *pDevice, bool bIsImage = false, XADDR nModuleAddress = -1); 57 | QString getCurrentRecordFileName(); 58 | virtual void adjustView(); 59 | virtual void reloadData(bool bSaveSelection); 60 | 61 | private slots: 62 | void on_tableViewRecords_customContextMenuRequested(const QPoint &pos); 63 | void showContext(const QString &sRecordFileName, QPoint point); 64 | void hexRecord(); 65 | void stringsRecord(); 66 | void entropyRecord(); 67 | void hashRecord(); 68 | void copyFileName(); 69 | void dumpRecord(); 70 | void handleAction(ACTION action); 71 | void on_lineEditFilter_textChanged(const QString &sString); 72 | void on_tableViewRecords_doubleClicked(const QModelIndex &index); 73 | void onTableElement_selected(const QItemSelection &itemSelected, const QItemSelection &itemDeselected); 74 | 75 | protected: 76 | virtual void registerShortcuts(bool bState); 77 | 78 | private: 79 | void loadRecords(); 80 | void setupTableView(); 81 | 82 | private: 83 | Ui::XArchiveWidget *ui; 84 | QIODevice *m_pDevice; 85 | XBinary::FT m_fileType; 86 | QList m_listRecords; 87 | QStandardItemModel *m_pModel; 88 | QSortFilterProxyModel *m_pFilterModel; 89 | QString m_sCurrentRecordFileName; 90 | qint64 m_nCurrentFileSize; 91 | }; 92 | 93 | #endif // XARCHIVEWIDGET_H 94 | -------------------------------------------------------------------------------- /unpackfileprocess.cpp: -------------------------------------------------------------------------------- 1 | /* Copyright (c) 2020-2025 hors 2 | * 3 | * Permission is hereby granted, free of charge, to any person obtaining a copy 4 | * of this software and associated documentation files (the "Software"), to deal 5 | * in the Software without restriction, including without limitation the rights 6 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 7 | * copies of the Software, and to permit persons to whom the Software is 8 | * furnished to do so, subject to the following conditions: 9 | * 10 | * The above copyright notice and this permission notice shall be included in 11 | * all copies or substantial portions of the Software. 12 | * 13 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 14 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 15 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 16 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 17 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 18 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 19 | * SOFTWARE. 20 | */ 21 | #include "unpackfileprocess.h" 22 | 23 | UnpackFileProcess::UnpackFileProcess(QObject *pParent) : XThreadObject(pParent) 24 | { 25 | m_pDevice = nullptr; 26 | m_pRecord = nullptr; 27 | m_pPdStruct = nullptr; 28 | } 29 | 30 | void UnpackFileProcess::setData(const QString &sFileName, XArchive::RECORD *pRecord, const QString &sResultFileName, XBinary::PDSTRUCT *pPdStruct) 31 | { 32 | m_sFileName = sFileName; 33 | m_pRecord = pRecord; 34 | m_sResultFileName = sResultFileName; 35 | m_pPdStruct = pPdStruct; 36 | } 37 | 38 | void UnpackFileProcess::setData(const QString &sFileName, const QString &sResultFileFolder, XBinary::PDSTRUCT *pPdStruct) 39 | { 40 | m_sFileName = sFileName; 41 | m_sResultFileFolder = sResultFileFolder; 42 | m_pPdStruct = pPdStruct; 43 | } 44 | 45 | void UnpackFileProcess::setData(QIODevice *pDevice, XArchive::RECORD *pRecord, const QString &sResultFileName, XBinary::PDSTRUCT *pPdStruct) 46 | { 47 | m_pDevice = pDevice; 48 | m_pRecord = pRecord; 49 | m_sResultFileName = sResultFileName; 50 | m_pPdStruct = pPdStruct; 51 | } 52 | 53 | void UnpackFileProcess::setData(QIODevice *pDevice, const QString &sResultFileFolder, XBinary::PDSTRUCT *pPdStruct) 54 | { 55 | m_pDevice = pDevice; 56 | m_sResultFileFolder = sResultFileFolder; 57 | m_pPdStruct = pPdStruct; 58 | } 59 | 60 | void UnpackFileProcess::process() 61 | { 62 | QElapsedTimer scanTimer; 63 | scanTimer.start(); 64 | 65 | qint32 _nFreeIndex = XBinary::getFreeIndex(m_pPdStruct); 66 | XBinary::setPdStructInit(m_pPdStruct, _nFreeIndex, 0); 67 | 68 | bool bResult = false; 69 | 70 | if (m_sFileName != "") { 71 | if (m_sResultFileName != "") { 72 | bResult = XArchives::decompressToFile(m_sFileName, m_pRecord, m_sResultFileName, 73 | m_pPdStruct); // TODO Error signals 74 | } else if (m_sResultFileFolder != "") { 75 | bResult = XArchives::decompressToFolder(m_sFileName, m_sResultFileFolder, m_pPdStruct); // TODO Error signals 76 | } 77 | } else if (m_pDevice) { 78 | if (m_sResultFileName != "") { 79 | bResult = XArchives::decompressToFile(m_pDevice, m_pRecord, m_sResultFileName, 80 | m_pPdStruct); // TODO Error signals 81 | } else if (m_sResultFileFolder != "") { 82 | bResult = XArchives::decompressToFolder(m_pDevice, m_sResultFileFolder, m_pPdStruct); // TODO Error signals 83 | } 84 | } 85 | 86 | if (!(bResult)) { 87 | XBinary::setPdStructStopped(m_pPdStruct); 88 | } 89 | 90 | XBinary::setPdStructFinished(m_pPdStruct, _nFreeIndex); 91 | 92 | emit completed(scanTimer.elapsed()); 93 | } 94 | -------------------------------------------------------------------------------- /dialogcreateviewmodel.cpp: -------------------------------------------------------------------------------- 1 | /* Copyright (c) 2020-2025 hors 2 | * 3 | * Permission is hereby granted, free of charge, to any person obtaining a copy 4 | * of this software and associated documentation files (the "Software"), to deal 5 | * in the Software without restriction, including without limitation the rights 6 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 7 | * copies of the Software, and to permit persons to whom the Software is 8 | * furnished to do so, subject to the following conditions: 9 | * 10 | * The above copyright notice and this permission notice shall be included in 11 | * all copies or substantial portions of the Software. 12 | * 13 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 14 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 15 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 16 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 17 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 18 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 19 | * SOFTWARE. 20 | */ 21 | #include "dialogcreateviewmodel.h" 22 | 23 | #include 24 | 25 | DialogCreateViewModel::DialogCreateViewModel(QWidget *pParent) : XDialogProcess(pParent) 26 | { 27 | m_pCreateViewModelProcess.reset(new CreateViewModelProcess); 28 | m_pThread.reset(new QThread); 29 | m_bIsRunning = false; 30 | 31 | m_pCreateViewModelProcess->moveToThread(m_pThread.data()); 32 | 33 | connect(m_pThread.data(), SIGNAL(started()), m_pCreateViewModelProcess.data(), SLOT(process())); 34 | connect(m_pCreateViewModelProcess.data(), SIGNAL(completed(qint64)), this, SLOT(onCompleted(qint64))); 35 | connect(m_pCreateViewModelProcess.data(), SIGNAL(progressValueChanged(qint32)), this, SLOT(onProgressValueChanged(qint32))); 36 | connect(m_pCreateViewModelProcess.data(), SIGNAL(progressMessageChanged(const QString &)), this, SLOT(onProgressMessageChanged(const QString &))); 37 | connect(m_pCreateViewModelProcess.data(), SIGNAL(errorMessage(const QString &)), this, SLOT(onErrorMessage(const QString &))); 38 | } 39 | 40 | DialogCreateViewModel::~DialogCreateViewModel() 41 | { 42 | if (m_bIsRunning) { 43 | stop(); 44 | waitForFinished(); 45 | m_bIsRunning = false; 46 | } 47 | 48 | if (m_pThread) { 49 | m_pThread->quit(); 50 | m_pThread->wait(); 51 | } 52 | } 53 | 54 | void DialogCreateViewModel::setData(CreateViewModelProcess::TYPE type, const QString &sName, XBinary::FT fileType, QList *pListArchiveRecords, 55 | QStandardItemModel **ppTreeModel, QStandardItemModel **ppTableModel, const QSet &stFilterFileTypes, 56 | QList *pListViewRecords) 57 | { 58 | if (m_bIsRunning) { 59 | return; // Already running, ignore 60 | } 61 | 62 | // Validate inputs 63 | if (!pListArchiveRecords || !ppTreeModel || !ppTableModel || !pListViewRecords) { 64 | QMessageBox::critical(this, tr("Error"), tr("Invalid parameters provided")); 65 | return; 66 | } 67 | 68 | if (sName.isEmpty()) { 69 | QMessageBox::critical(this, tr("Error"), tr("File name cannot be empty")); 70 | return; 71 | } 72 | 73 | m_bIsRunning = true; 74 | m_pCreateViewModelProcess->setData(type, sName, fileType, pListArchiveRecords, ppTreeModel, ppTableModel, stFilterFileTypes, pListViewRecords, getPdStruct()); 75 | m_pThread->start(); 76 | } 77 | 78 | void DialogCreateViewModel::onProgressValueChanged(qint32 nValue) 79 | { 80 | Q_UNUSED(nValue) 81 | // Progress is handled through PDSTRUCT by the parent class 82 | } 83 | 84 | void DialogCreateViewModel::onProgressMessageChanged(const QString &sText) 85 | { 86 | Q_UNUSED(sText) 87 | // Additional progress messages can be displayed here if needed 88 | } 89 | 90 | void DialogCreateViewModel::onErrorMessage(const QString &sText) 91 | { 92 | QMessageBox::critical(this, tr("Error"), sText); 93 | } 94 | 95 | void DialogCreateViewModel::onCompleted(qint64 nElapsed) 96 | { 97 | m_bIsRunning = false; 98 | XDialogProcess::onCompleted(nElapsed); 99 | } 100 | -------------------------------------------------------------------------------- /archive_widget.h: -------------------------------------------------------------------------------- 1 | /* Copyright (c) 2020-2025 hors 2 | * 3 | * Permission is hereby granted, free of charge, to any person obtaining a copy 4 | * of this software and associated documentation files (the "Software"), to deal 5 | * in the Software without restriction, including without limitation the rights 6 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 7 | * copies of the Software, and to permit persons to whom the Software is 8 | * furnished to do so, subject to the following conditions: 9 | * 10 | * The above copyright notice and this permission notice shall be included in 11 | * all copies or substantial portions of the Software. 12 | * 13 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 14 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 15 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 16 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 17 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 18 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 19 | * SOFTWARE. 20 | */ 21 | #ifndef ARCHIVE_WIDGET_H 22 | #define ARCHIVE_WIDGET_H 23 | 24 | #include "dialogcreateviewmodel.h" 25 | #include "dialogdex.h" 26 | #include "dialogelf.h" 27 | #include "dialogentropy.h" 28 | #include "dialoghash.h" 29 | #include "dialoghexview.h" 30 | #include "dialogle.h" 31 | #include "dialogmach.h" 32 | #include "dialogmsdos.h" 33 | #include "dialogne.h" 34 | #include "dialogpe.h" 35 | #include "dialogsearchstrings.h" 36 | #include "dialogshowimage.h" 37 | #include "dialognfdscan.h" 38 | #include "dialogtextinfo.h" 39 | #include "dialogunpackfile.h" 40 | #include "xandroidbinary.h" 41 | #include "xarchives.h" 42 | 43 | namespace Ui { 44 | class Archive_widget; 45 | } 46 | 47 | class Archive_widget : public XShortcutsWidget { 48 | Q_OBJECT 49 | 50 | enum ACTION { 51 | ACTION_OPEN = 0, 52 | ACTION_SCAN, 53 | ACTION_HEX, 54 | ACTION_STRINGS, 55 | ACTION_ENTROPY, 56 | ACTION_HASH, 57 | ACTION_COPYFILENAME, 58 | ACTION_DUMP 59 | // TODO more 60 | // TODO Check 61 | }; 62 | 63 | public: 64 | explicit Archive_widget(QWidget *pParent = nullptr); 65 | ~Archive_widget(); 66 | 67 | // TODO setOptions 68 | void setFileName(const QString &sFileName, XBinary::FT fileType, const FW_DEF::OPTIONS &options, 69 | const QSet &stAvailableOpenFileTypes); // TODO options for Viewers TODO Device 70 | void setDirectoryName(const QString &sDirectoryName, const FW_DEF::OPTIONS &options, const QSet &stAvailableOpenFileTypes); 71 | void setData(CreateViewModelProcess::TYPE type, const QString &sName, XBinary::FT fileType, const FW_DEF::OPTIONS &options, 72 | const QSet &stAvailableOpenFileTypes); 73 | QString getCurrentRecordFileName(); 74 | QList getRecordsByFileType(XBinary::FT fileType); 75 | virtual void adjustView(); 76 | virtual void reloadData(bool bSaveSelection); 77 | 78 | public slots: 79 | void openRecord(); 80 | 81 | private slots: 82 | void on_treeViewArchive_customContextMenuRequested(const QPoint &pos); 83 | void on_tableViewArchive_customContextMenuRequested(const QPoint &pos); 84 | void showContext(const QString &sRecordFileName, bool bIsRoot, QPoint point); 85 | bool isOpenAvailable(const QString &sRecordFileName, bool bIsRoot); 86 | void scanRecord(); 87 | void hexRecord(); 88 | void stringsRecord(); 89 | void entropyRecord(); 90 | void hashRecord(); 91 | void copyFileName(); 92 | void dumpRecord(); 93 | void handleAction(ACTION action); 94 | void _handleActionDevice(ACTION action, QIODevice *pDevice); 95 | void _handleActionOpenFile(const QString &sFileName, const QString &sTitle, bool bReadWrite); 96 | void on_comboBoxType_currentIndexChanged(int nIndex); 97 | void on_lineEditFilter_textChanged(const QString &sString); 98 | void on_treeViewArchive_doubleClicked(const QModelIndex &index); 99 | void on_tableViewArchive_doubleClicked(const QModelIndex &index); 100 | void onTreeElement_selected(const QItemSelection &itemSelected, const QItemSelection &itemDeselected); // TrackSelection 101 | void onTableElement_selected(const QItemSelection &itemSelected, const QItemSelection &itemDeselected); // TrackSelection 102 | 103 | protected: 104 | virtual void registerShortcuts(bool bState); 105 | 106 | signals: 107 | void openAvailable(bool bState); 108 | 109 | private: 110 | Ui::Archive_widget *ui; 111 | CreateViewModelProcess::TYPE m_type; 112 | QString m_sName; 113 | FW_DEF::OPTIONS m_options; 114 | QList m_listRecords; 115 | QSortFilterProxyModel *m_pFilterTable; // TODO remove 116 | QSet m_stAvailableOpenFileTypes; 117 | qint64 m_nCurrentFileSize; 118 | bool m_bCurrentFileIsRoot; 119 | QString m_sCurrentRecordFileName; 120 | QList m_listViewRecords; 121 | }; 122 | 123 | #endif // ARCHIVE_WIDGET_H 124 | -------------------------------------------------------------------------------- /archive_widget.ui: -------------------------------------------------------------------------------- 1 | 2 | 3 | Archive_widget 4 | 5 | 6 | 7 | 0 8 | 0 9 | 564 10 | 394 11 | 12 | 13 | 14 | Form 15 | 16 | 17 | 18 | 0 19 | 20 | 21 | 0 22 | 23 | 24 | 0 25 | 26 | 27 | 0 28 | 29 | 30 | 31 | 32 | 33 | 34 | Type 35 | 36 | 37 | 38 | 2 39 | 40 | 41 | 2 42 | 43 | 44 | 2 45 | 46 | 47 | 2 48 | 49 | 50 | 51 | 52 | 53 | 54 | 55 | 56 | 57 | 58 | Filter 59 | 60 | 61 | 62 | 2 63 | 64 | 65 | 2 66 | 67 | 68 | 2 69 | 70 | 71 | 2 72 | 73 | 74 | 75 | 76 | 77 | 78 | 79 | 80 | 81 | 82 | 83 | 84 | 0 85 | 86 | 87 | 88 | 89 | 0 90 | 91 | 92 | 0 93 | 94 | 95 | 0 96 | 97 | 98 | 0 99 | 100 | 101 | 102 | 103 | Qt::CustomContextMenu 104 | 105 | 106 | QAbstractItemView::NoEditTriggers 107 | 108 | 109 | false 110 | 111 | 112 | 113 | 114 | 115 | 116 | 117 | 118 | 0 119 | 120 | 121 | 0 122 | 123 | 124 | 0 125 | 126 | 127 | 0 128 | 129 | 130 | 131 | 132 | Qt::CustomContextMenu 133 | 134 | 135 | QAbstractItemView::NoEditTriggers 136 | 137 | 138 | QAbstractItemView::SingleSelection 139 | 140 | 141 | QAbstractItemView::SelectRows 142 | 143 | 144 | false 145 | 146 | 147 | 20 148 | 149 | 150 | 20 151 | 152 | 153 | false 154 | 155 | 156 | 157 | 158 | 159 | 160 | 161 | 162 | 163 | 164 | 165 | 166 | -------------------------------------------------------------------------------- /dialogshowimage.cpp: -------------------------------------------------------------------------------- 1 | /* Copyright (c) 2020-2025 hors 2 | * 3 | * Permission is hereby granted, free of charge, to any person obtaining a copy 4 | * of this software and associated documentation files (the "Software"), to deal 5 | * in the Software without restriction, including without limitation the rights 6 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 7 | * copies of the Software, and to permit persons to whom the Software is 8 | * furnished to do so, subject to the following conditions: 9 | * 10 | * The above copyright notice and this permission notice shall be included in 11 | * all copies or substantial portions of the Software. 12 | * 13 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 14 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 15 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 16 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 17 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 18 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 19 | * SOFTWARE. 20 | */ 21 | #include "dialogshowimage.h" 22 | 23 | #include 24 | #include 25 | #include 26 | #include 27 | #include 28 | #include 29 | #include 30 | #include 31 | #include 32 | #include 33 | #include 34 | 35 | #include "ui_dialogshowimage.h" 36 | 37 | DialogShowImage::DialogShowImage(QWidget *pParent, const QString &sFileName, const QString &sTitle) : XShortcutsDialog(pParent, true), ui(new Ui::DialogShowImage) 38 | { 39 | ui->setupUi(this); 40 | 41 | setWindowTitle(sTitle); 42 | 43 | // Check if file exists 44 | if (!QFileInfo::exists(sFileName)) { 45 | QMessageBox::critical(this, tr("Error"), tr("Image file does not exist: %1").arg(sFileName)); 46 | return; 47 | } 48 | 49 | // Load the image 50 | QPixmap pixmap(sFileName); 51 | if (pixmap.isNull()) { 52 | QMessageBox::critical(this, tr("Error"), tr("Failed to load image: %1").arg(sFileName)); 53 | return; 54 | } 55 | 56 | // Store original pixmap 57 | m_originalPixmap = pixmap; 58 | m_currentPixmap = pixmap; 59 | m_zoomFactor = 1.0; 60 | m_fitToWindow = true; // Start with fit to window 61 | 62 | // Set initial display 63 | updateImageDisplay(); 64 | 65 | // Set window size based on image size, but constrain to reasonable limits 66 | QSize imageSize = pixmap.size(); 67 | QSize maxSize(1200, 800); // Reasonable maximum window size 68 | 69 | if (imageSize.width() > maxSize.width() || imageSize.height() > maxSize.height()) { 70 | imageSize.scale(maxSize, Qt::KeepAspectRatio); 71 | } 72 | 73 | resize(imageSize + QSize(20, 60)); // Add some padding for window decorations 74 | 75 | // Display image information 76 | updateImageInfo(); 77 | } 78 | 79 | DialogShowImage::~DialogShowImage() 80 | { 81 | delete ui; 82 | } 83 | 84 | void DialogShowImage::adjustView() 85 | { 86 | if (m_fitToWindow) { 87 | updateImageDisplay(); 88 | } 89 | } 90 | 91 | void DialogShowImage::on_pushButtonClose_clicked() 92 | { 93 | this->close(); 94 | } 95 | 96 | void DialogShowImage::registerShortcuts(bool bState) 97 | { 98 | if (bState) { 99 | // Zoom shortcuts 100 | // getShortcuts()->addShortcut(Qt::Key_Plus, this, SLOT(zoomIn())); 101 | // getShortcuts()->addShortcut(Qt::Key_Equal, this, SLOT(zoomIn())); 102 | // getShortcuts()->addShortcut(Qt::CTRL + Qt::Key_Plus, this, SLOT(zoomIn())); 103 | // getShortcuts()->addShortcut(Qt::CTRL + Qt::Key_Equal, this, SLOT(zoomIn())); 104 | // getShortcuts()->addShortcut(Qt::Key_Minus, this, SLOT(zoomOut())); 105 | // getShortcuts()->addShortcut(Qt::CTRL + Qt::Key_Minus, this, SLOT(zoomOut())); 106 | // getShortcuts()->addShortcut(Qt::Key_0, this, SLOT(actualSize())); 107 | // getShortcuts()->addShortcut(Qt::CTRL + Qt::Key_0, this, SLOT(actualSize())); 108 | // getShortcuts()->addShortcut(Qt::Key_F, this, SLOT(fitToWindow())); 109 | 110 | // // Close shortcuts 111 | // getShortcuts()->addShortcut(Qt::Key_Escape, this, SLOT(close())); 112 | // getShortcuts()->addShortcut(Qt::CTRL + Qt::Key_W, this, SLOT(close())); 113 | } else { 114 | // Remove shortcuts when disabled 115 | // getShortcuts()->clear(); 116 | } 117 | } 118 | 119 | void DialogShowImage::updateImageDisplay() 120 | { 121 | if (m_fitToWindow) { 122 | // Scale to fit the label size while maintaining aspect ratio 123 | QSize labelSize = ui->labelImage->size(); 124 | QPixmap scaledPixmap = m_originalPixmap.scaled(labelSize, Qt::KeepAspectRatio, Qt::SmoothTransformation); 125 | ui->labelImage->setPixmap(scaledPixmap); 126 | } else { 127 | // Apply zoom factor 128 | QSize newSize = m_originalPixmap.size() * m_zoomFactor; 129 | QPixmap scaledPixmap = m_originalPixmap.scaled(newSize, Qt::KeepAspectRatio, Qt::SmoothTransformation); 130 | ui->labelImage->setPixmap(scaledPixmap); 131 | } 132 | } 133 | 134 | void DialogShowImage::setZoomFactor(qreal factor) 135 | { 136 | m_zoomFactor = qMax(0.1, qMin(5.0, factor)); // Limit zoom between 10% and 500% 137 | m_fitToWindow = false; 138 | updateImageDisplay(); 139 | updateImageInfo(); 140 | adjustView(); 141 | } 142 | 143 | void DialogShowImage::zoomIn() 144 | { 145 | setZoomFactor(m_zoomFactor * 1.2); 146 | } 147 | 148 | void DialogShowImage::zoomOut() 149 | { 150 | setZoomFactor(m_zoomFactor / 1.2); 151 | } 152 | 153 | void DialogShowImage::fitToWindow() 154 | { 155 | m_fitToWindow = true; 156 | updateImageDisplay(); 157 | updateImageInfo(); 158 | } 159 | 160 | void DialogShowImage::actualSize() 161 | { 162 | m_zoomFactor = 1.0; 163 | m_fitToWindow = false; 164 | updateImageDisplay(); 165 | updateImageInfo(); 166 | } 167 | 168 | void DialogShowImage::contextMenuEvent(QContextMenuEvent *event) 169 | { 170 | QMenu menu(this); 171 | 172 | // Zoom actions 173 | QAction *zoomInAction = menu.addAction(tr("Zoom In"), this, SLOT(zoomIn())); 174 | zoomInAction->setShortcut(QKeySequence::ZoomIn); 175 | 176 | QAction *zoomOutAction = menu.addAction(tr("Zoom Out"), this, SLOT(zoomOut())); 177 | zoomOutAction->setShortcut(QKeySequence::ZoomOut); 178 | 179 | QAction *actualSizeAction = menu.addAction(tr("Actual Size"), this, SLOT(actualSize())); 180 | actualSizeAction->setShortcut(tr("Ctrl+0")); 181 | 182 | QAction *fitToWindowAction = menu.addAction(tr("Fit to Window"), this, SLOT(fitToWindow())); 183 | fitToWindowAction->setShortcut(tr("F")); 184 | 185 | menu.addSeparator(); 186 | 187 | // Copy and save actions 188 | QAction *copyAction = menu.addAction(tr("Copy"), this, SLOT(copyToClipboard())); 189 | copyAction->setShortcut(QKeySequence::Copy); 190 | 191 | QAction *saveAsAction = menu.addAction(tr("Save As..."), this, SLOT(saveAs())); 192 | 193 | menu.addSeparator(); 194 | 195 | // Close action 196 | QAction *closeAction = menu.addAction(tr("Close"), this, SLOT(close())); 197 | closeAction->setShortcut(QKeySequence::Close); 198 | 199 | menu.exec(event->globalPos()); 200 | } 201 | 202 | void DialogShowImage::copyToClipboard() 203 | { 204 | if (!m_originalPixmap.isNull()) { 205 | QApplication::clipboard()->setPixmap(m_originalPixmap); 206 | } 207 | } 208 | 209 | void DialogShowImage::saveAs() 210 | { 211 | if (m_originalPixmap.isNull()) { 212 | return; 213 | } 214 | 215 | QString fileName = QFileDialog::getSaveFileName(this, tr("Save Image"), QStandardPaths::writableLocation(QStandardPaths::PicturesLocation), 216 | tr("Images (*.png *.jpg *.jpeg *.bmp *.gif)")); 217 | 218 | if (!fileName.isEmpty()) { 219 | if (!m_originalPixmap.save(fileName)) { 220 | QMessageBox::critical(this, tr("Error"), tr("Failed to save image to %1").arg(fileName)); 221 | } 222 | } 223 | } 224 | 225 | void DialogShowImage::updateImageInfo() 226 | { 227 | if (m_originalPixmap.isNull()) { 228 | ui->labelInfo->setText(tr("No image loaded")); 229 | return; 230 | } 231 | 232 | QSize size = m_originalPixmap.size(); 233 | QString format = "Unknown"; 234 | 235 | // Try to determine format from file extension 236 | QFileInfo fileInfo(windowTitle()); 237 | QString extension = fileInfo.suffix().toLower(); 238 | 239 | if (extension == "png") format = "PNG"; 240 | else if (extension == "jpg" || extension == "jpeg") format = "JPEG"; 241 | else if (extension == "bmp") format = "BMP"; 242 | else if (extension == "gif") format = "GIF"; 243 | else if (extension == "tiff" || extension == "tif") format = "TIFF"; 244 | 245 | QString info = tr("Size: %1 x %2 | Format: %3 | Zoom: %4%").arg(size.width()).arg(size.height()).arg(format).arg(qRound(m_zoomFactor * 100)); 246 | 247 | ui->labelInfo->setText(info); 248 | } 249 | 250 | void DialogShowImage::wheelEvent(QWheelEvent *event) 251 | { 252 | if (event->modifiers() & Qt::ControlModifier) { 253 | // Ctrl + wheel = zoom 254 | if (event->angleDelta().y() > 0) { 255 | zoomIn(); 256 | } else { 257 | zoomOut(); 258 | } 259 | event->accept(); 260 | } else { 261 | // Pass to parent for default handling 262 | QWidget::wheelEvent(event); 263 | } 264 | } 265 | -------------------------------------------------------------------------------- /createviewmodelprocess.cpp: -------------------------------------------------------------------------------- 1 | /* Copyright (c) 2020-2025 hors 2 | * 3 | * Permission is hereby granted, free of charge, to any person obtaining a copy 4 | * of this software and associated documentation files (the "Software"), to deal 5 | * in the Software without restriction, including without limitation the rights 6 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 7 | * copies of the Software, and to permit persons to whom the Software is 8 | * furnished to do so, subject to the following conditions: 9 | * 10 | * The above copyright notice and this permission notice shall be included in 11 | * all copies or substantial portions of the Software. 12 | * 13 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 14 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 15 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 16 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 17 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 18 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 19 | * SOFTWARE. 20 | */ 21 | #include "createviewmodelprocess.h" 22 | 23 | CreateViewModelProcess::CreateViewModelProcess(QObject *pParent) : QObject(pParent) 24 | { 25 | m_pPdStruct = nullptr; 26 | m_type = TYPE_UNKNOWN; 27 | m_fileType = XBinary::FT_UNKNOWN; 28 | } 29 | 30 | void CreateViewModelProcess::setData(TYPE type, const QString &sName, XBinary::FT fileType, QList *pListArchiveRecords, 31 | QStandardItemModel **ppTreeModel, QStandardItemModel **ppTableModel, const QSet &stFilterFileTypes, 32 | QList *pListViewRecords, XBinary::PDSTRUCT *pPdStruct) 33 | { 34 | // Validate inputs 35 | if (!pListArchiveRecords || !ppTreeModel || !ppTableModel || !pListViewRecords) { 36 | emit errorMessage("Invalid parameters provided to CreateViewModelProcess"); 37 | return; 38 | } 39 | 40 | this->m_type = type; 41 | this->m_sName = sName; 42 | this->m_fileType = fileType; 43 | this->m_pListArchiveRecords = pListArchiveRecords; 44 | this->m_ppTreeModel = ppTreeModel; 45 | this->m_ppTableModel = ppTableModel; 46 | this->m_stFilterFileTypes = stFilterFileTypes; 47 | this->m_pListViewRecords = pListViewRecords; 48 | this->m_pPdStruct = pPdStruct; 49 | } 50 | 51 | void CreateViewModelProcess::process() 52 | { 53 | QElapsedTimer scanTimer; 54 | scanTimer.start(); 55 | 56 | emit progressValueChanged(0); 57 | emit progressMessageChanged("Initializing..."); 58 | 59 | XBinary::FT ftPref = m_fileType; 60 | 61 | if (m_type == TYPE_FILE) { 62 | if (ftPref == XBinary::FT_UNKNOWN) { 63 | QSet stFT = XFormats::getFileTypes(m_sName, true, m_pPdStruct); 64 | ftPref = XBinary::_getPrefFileType(&stFT); 65 | } 66 | 67 | *m_pListArchiveRecords = XArchives::getRecords(m_sName, ftPref, -1, m_pPdStruct); 68 | 69 | if (m_pListArchiveRecords->isEmpty()) { 70 | emit errorMessage("Failed to read archive records"); 71 | emit completed(scanTimer.elapsed()); 72 | return; 73 | } 74 | } else if (m_type == TYPE_DIRECTORY) { 75 | *m_pListArchiveRecords = XArchives::getRecordsFromDirectory(m_sName, -1, m_pPdStruct); 76 | 77 | if (m_pListArchiveRecords->isEmpty()) { 78 | emit errorMessage("No files found in directory"); 79 | emit completed(scanTimer.elapsed()); 80 | return; 81 | } 82 | } 83 | 84 | qint64 nFileSize = XBinary::getSize(m_sName); 85 | 86 | qint32 nNumberOfRecords = m_pListArchiveRecords->count(); 87 | 88 | qint32 _nFreeIndex = XBinary::getFreeIndex(m_pPdStruct); 89 | XBinary::setPdStructInit(m_pPdStruct, _nFreeIndex, nNumberOfRecords); 90 | 91 | if (nNumberOfRecords == 0) { 92 | RECORD _record = {}; 93 | _record.sRecordName = m_sName; 94 | _record.ft = ftPref; 95 | _record.bIsVirtual = false; 96 | 97 | m_pListViewRecords->append(_record); 98 | } 99 | 100 | *m_ppTreeModel = new QStandardItemModel; 101 | (*m_ppTreeModel)->setColumnCount(2); 102 | 103 | *m_ppTableModel = new QStandardItemModel; 104 | (*m_ppTableModel)->setColumnCount(3); 105 | 106 | QString sBaseName = QFileInfo(m_sName).fileName(); 107 | 108 | QStandardItem *pRootItemName = new QStandardItem; 109 | pRootItemName->setText(sBaseName); 110 | pRootItemName->setData(m_sName, Qt::UserRole + UR_PATH); 111 | pRootItemName->setData(nFileSize, Qt::UserRole + UR_SIZE); 112 | pRootItemName->setData(true, Qt::UserRole + UR_ISROOT); 113 | 114 | (*m_ppTreeModel)->setItem(0, 0, pRootItemName); 115 | 116 | QStandardItem *pRootItemSize = new QStandardItem; 117 | pRootItemSize->setText(QString::number(nFileSize)); 118 | pRootItemSize->setTextAlignment(Qt::AlignRight); 119 | 120 | (*m_ppTreeModel)->setItem(0, 1, pRootItemSize); 121 | 122 | bool bFilter = m_stFilterFileTypes.count(); 123 | 124 | QMap mapItems; 125 | 126 | for (qint32 i = 0, j = 0; (i < nNumberOfRecords) && XBinary::isPdStructNotCanceled(m_pPdStruct); i++) { 127 | XArchive::RECORD record = m_pListArchiveRecords->at(i); 128 | QString sRecordFileName = record.spInfo.sRecordName; 129 | 130 | // Emit progress update 131 | emit progressValueChanged((i * 100) / nNumberOfRecords); 132 | emit progressMessageChanged(QString("Processing: %1").arg(sRecordFileName)); 133 | 134 | bool bAdd = true; 135 | 136 | QSet stFT; 137 | 138 | if (m_type == TYPE_FILE) { 139 | QByteArray baData = XArchives::decompress(m_sName, &record, m_pPdStruct); 140 | 141 | stFT = XFormats::getFileTypes(&baData, true); 142 | } else if (m_type == TYPE_DIRECTORY) { 143 | stFT = XFormats::getFileTypes(sRecordFileName, true); 144 | } 145 | 146 | XBinary::FT ftPref = XBinary::_getPrefFileType(&stFT); 147 | 148 | RECORD _record = {}; 149 | _record.sRecordName = sRecordFileName; 150 | _record.ft = ftPref; 151 | _record.bIsVirtual = true; 152 | 153 | m_pListViewRecords->append(_record); 154 | 155 | if (bFilter) { 156 | bAdd = XBinary::isFileTypePresent(&stFT, &m_stFilterFileTypes); 157 | } 158 | 159 | if (bAdd) { 160 | QString _sRecordFileName = sRecordFileName; 161 | 162 | while (_sRecordFileName.size() > 1) { 163 | if (_sRecordFileName.at(0) == QChar('/')) { 164 | _sRecordFileName = _sRecordFileName.mid(1, -1); 165 | } else { 166 | break; 167 | } 168 | } 169 | 170 | qint32 nNumberOfParts = _sRecordFileName.count("/"); 171 | 172 | for (qint32 k = 0; k <= nNumberOfParts; k++) { 173 | QString sPart = _sRecordFileName.section("/", k, k); 174 | QString sRelPart; 175 | 176 | if (sPart != "") { 177 | if (k != nNumberOfParts) { 178 | sRelPart = _sRecordFileName.section("/", 0, k); 179 | } else { 180 | sRelPart = _sRecordFileName; 181 | } 182 | 183 | if (!mapItems.contains(sRelPart)) { 184 | QStandardItem *pItemName = new QStandardItem; 185 | pItemName->setText(sPart); 186 | 187 | if (k == (nNumberOfParts)) { 188 | pItemName->setData(sRecordFileName, Qt::UserRole + UR_PATH); 189 | pItemName->setData(record.spInfo.nUncompressedSize, Qt::UserRole + UR_SIZE); 190 | pItemName->setData(false, Qt::UserRole + UR_ISROOT); 191 | pItemName->setData(ftPref, Qt::UserRole + UR_FT); 192 | } 193 | 194 | QStandardItem *pItemParent = nullptr; 195 | 196 | if (k == 0) { 197 | pItemParent = pRootItemName; 198 | } else { 199 | pItemParent = mapItems.value(_sRecordFileName.section("/", 0, k - 1)); 200 | } 201 | 202 | QList listItems; 203 | 204 | listItems.append(pItemName); 205 | 206 | if (k == (nNumberOfParts)) { 207 | QStandardItem *pItemSize = new QStandardItem; 208 | pItemSize->setData(record.spInfo.nUncompressedSize, Qt::DisplayRole); 209 | pItemSize->setTextAlignment(Qt::AlignRight); 210 | 211 | listItems.append(pItemSize); 212 | } 213 | 214 | pItemParent->appendRow(listItems); 215 | 216 | mapItems.insert(sRelPart, pItemName); 217 | } 218 | } 219 | } 220 | 221 | QList listItems; 222 | 223 | QStandardItem *pItemNumber = new QStandardItem; 224 | pItemNumber->setData(j, Qt::DisplayRole); 225 | pItemNumber->setTextAlignment(Qt::AlignRight); 226 | pItemNumber->setData(sRecordFileName, Qt::UserRole + UR_PATH); 227 | pItemNumber->setData(record.spInfo.nUncompressedSize, Qt::UserRole + UR_SIZE); 228 | pItemNumber->setData(false, Qt::UserRole + UR_ISROOT); 229 | pItemNumber->setData(ftPref, Qt::UserRole + UR_FT); 230 | listItems.append(pItemNumber); 231 | 232 | QStandardItem *pItemName = new QStandardItem; 233 | pItemName->setText(sRecordFileName); 234 | listItems.append(pItemName); 235 | 236 | QStandardItem *pItemSize = new QStandardItem; 237 | pItemSize->setData(record.spInfo.nUncompressedSize, Qt::DisplayRole); 238 | pItemSize->setTextAlignment(Qt::AlignRight); 239 | listItems.append(pItemSize); 240 | 241 | (*m_ppTableModel)->appendRow(listItems); 242 | 243 | j++; 244 | } 245 | 246 | XBinary::setPdStructCurrentIncrement(m_pPdStruct, _nFreeIndex); 247 | XBinary::setPdStructStatus(m_pPdStruct, _nFreeIndex, m_pListArchiveRecords->at(i).spInfo.sRecordName); 248 | } 249 | 250 | (*m_ppTreeModel)->setHeaderData(0, Qt::Horizontal, tr("File")); 251 | (*m_ppTreeModel)->setHeaderData(1, Qt::Horizontal, tr("Size")); 252 | 253 | (*m_ppTableModel)->setHeaderData(0, Qt::Horizontal, ""); 254 | (*m_ppTableModel)->setHeaderData(1, Qt::Horizontal, tr("File")); 255 | (*m_ppTableModel)->setHeaderData(2, Qt::Horizontal, tr("Size")); 256 | 257 | XBinary::setPdStructFinished(m_pPdStruct, _nFreeIndex); 258 | 259 | emit progressValueChanged(100); 260 | emit progressMessageChanged("Completed"); 261 | 262 | emit completed(scanTimer.elapsed()); 263 | } 264 | -------------------------------------------------------------------------------- /xarchivewidget.cpp: -------------------------------------------------------------------------------- 1 | /* Copyright (c) 2020-2025 hors 2 | * 3 | * Permission is hereby granted, free of charge, to any person obtaining a copy 4 | * of this software and associated documentation files (the "Software"), to deal 5 | * in the Software without restriction, including without limitation the rights 6 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 7 | * copies of the Software, and to permit persons to whom the Software is 8 | * furnished to do so, subject to the following conditions: 9 | * 10 | * The above copyright notice and this permission notice shall be included in 11 | * all copies or substantial portions of the Software. 12 | * 13 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 14 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 15 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 16 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 17 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 18 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 19 | * SOFTWARE. 20 | */ 21 | #include "xarchivewidget.h" 22 | 23 | #include "ui_xarchivewidget.h" 24 | 25 | XArchiveWidget::XArchiveWidget(QWidget *pParent) : XShortcutsWidget(pParent), ui(new Ui::XArchiveWidget) 26 | { 27 | ui->setupUi(this); 28 | 29 | m_pDevice = nullptr; 30 | m_fileType = XBinary::FT_UNKNOWN; 31 | m_pModel = nullptr; 32 | m_pFilterModel = new QSortFilterProxyModel(this); 33 | m_nCurrentFileSize = 0; 34 | 35 | setupTableView(); 36 | } 37 | 38 | XArchiveWidget::~XArchiveWidget() 39 | { 40 | if (m_pModel) { 41 | delete m_pModel; 42 | } 43 | 44 | delete ui; 45 | } 46 | 47 | void XArchiveWidget::setData(XBinary::FT fileType, QIODevice *pDevice, bool bIsImage, XADDR nModuleAddress) 48 | { 49 | Q_UNUSED(bIsImage) 50 | Q_UNUSED(nModuleAddress) 51 | 52 | m_fileType = fileType; 53 | m_pDevice = pDevice; 54 | 55 | if (m_pDevice) { 56 | loadRecords(); 57 | } 58 | } 59 | 60 | QString XArchiveWidget::getCurrentRecordFileName() 61 | { 62 | return m_sCurrentRecordFileName; 63 | } 64 | 65 | void XArchiveWidget::adjustView() 66 | { 67 | } 68 | 69 | void XArchiveWidget::reloadData(bool bSaveSelection) 70 | { 71 | Q_UNUSED(bSaveSelection) 72 | 73 | loadRecords(); 74 | } 75 | 76 | void XArchiveWidget::on_tableViewRecords_customContextMenuRequested(const QPoint &pos) 77 | { 78 | QModelIndexList listIndexes = ui->tableViewRecords->selectionModel()->selectedIndexes(); 79 | 80 | if (listIndexes.size() > 0) { 81 | showContext(m_sCurrentRecordFileName, ui->tableViewRecords->viewport()->mapToGlobal(pos)); 82 | } 83 | } 84 | 85 | void XArchiveWidget::showContext(const QString &sRecordFileName, QPoint point) 86 | { 87 | if (sRecordFileName != "") { 88 | QMenu contextMenu(this); 89 | 90 | QAction actionHex(tr("Hex"), this); 91 | connect(&actionHex, SIGNAL(triggered()), this, SLOT(hexRecord())); 92 | contextMenu.addAction(&actionHex); 93 | 94 | QAction actionStrings(tr("Strings"), this); 95 | connect(&actionStrings, SIGNAL(triggered()), this, SLOT(stringsRecord())); 96 | contextMenu.addAction(&actionStrings); 97 | 98 | QAction actionEntropy(tr("Entropy"), this); 99 | connect(&actionEntropy, SIGNAL(triggered()), this, SLOT(entropyRecord())); 100 | contextMenu.addAction(&actionEntropy); 101 | 102 | QAction actionHash(tr("Hash"), this); 103 | connect(&actionHash, SIGNAL(triggered()), this, SLOT(hashRecord())); 104 | contextMenu.addAction(&actionHash); 105 | 106 | QMenu menuCopy(tr("Copy"), this); 107 | QAction actionCopyFilename(tr("File name"), this); 108 | connect(&actionCopyFilename, SIGNAL(triggered()), this, SLOT(copyFileName())); 109 | menuCopy.addAction(&actionCopyFilename); 110 | contextMenu.addMenu(&menuCopy); 111 | 112 | QAction actionDump(tr("Dump to file"), this); 113 | connect(&actionDump, SIGNAL(triggered()), this, SLOT(dumpRecord())); 114 | contextMenu.addAction(&actionDump); 115 | 116 | contextMenu.exec(point); 117 | } 118 | } 119 | 120 | void XArchiveWidget::hexRecord() 121 | { 122 | handleAction(ACTION_HEX); 123 | } 124 | 125 | void XArchiveWidget::stringsRecord() 126 | { 127 | handleAction(ACTION_STRINGS); 128 | } 129 | 130 | void XArchiveWidget::entropyRecord() 131 | { 132 | handleAction(ACTION_ENTROPY); 133 | } 134 | 135 | void XArchiveWidget::hashRecord() 136 | { 137 | handleAction(ACTION_HASH); 138 | } 139 | 140 | void XArchiveWidget::copyFileName() 141 | { 142 | handleAction(ACTION_COPYFILENAME); 143 | } 144 | 145 | void XArchiveWidget::dumpRecord() 146 | { 147 | handleAction(ACTION_DUMP); 148 | } 149 | 150 | void XArchiveWidget::handleAction(XArchiveWidget::ACTION action) 151 | { 152 | QString sRecordFileName = m_sCurrentRecordFileName; 153 | 154 | if (sRecordFileName != "") { 155 | if (action == ACTION_COPYFILENAME) { 156 | QGuiApplication::clipboard()->setText(sRecordFileName); 157 | } else if (action == ACTION_DUMP) { 158 | XArchive::RECORD record = XArchive::getArchiveRecord(sRecordFileName, &m_listRecords); 159 | QString sSaveFileName = QFileInfo(record.spInfo.sRecordName).fileName(); 160 | 161 | sSaveFileName = QFileDialog::getSaveFileName(this, tr("Save file"), sSaveFileName, QFileInfo(record.spInfo.sRecordName).completeSuffix()); 162 | 163 | if (sSaveFileName != "") { 164 | if (m_pDevice) { 165 | XArchive archive(m_pDevice); 166 | if (!archive.decompressToFile(&record, sSaveFileName)) { 167 | QMessageBox::critical(this, tr("Error"), tr("Cannot save file")); 168 | } 169 | } 170 | } 171 | } else { 172 | XArchive::RECORD record = XArchive::getArchiveRecord(sRecordFileName, &m_listRecords); 173 | 174 | if (m_pDevice) { 175 | XArchive archive(m_pDevice); 176 | QByteArray baData = archive.decompress(&record); 177 | 178 | if (!baData.isEmpty()) { 179 | QBuffer buffer; 180 | buffer.setBuffer(&baData); 181 | 182 | if (buffer.open(QIODevice::ReadOnly)) { 183 | if (action == ACTION_HEX) { 184 | QMessageBox::information(this, tr("Info"), tr("Hex view not implemented yet")); 185 | } else if (action == ACTION_STRINGS) { 186 | QMessageBox::information(this, tr("Info"), tr("Strings view not implemented yet")); 187 | } else if (action == ACTION_ENTROPY) { 188 | QMessageBox::information(this, tr("Info"), tr("Entropy view not implemented yet")); 189 | } else if (action == ACTION_HASH) { 190 | QMessageBox::information(this, tr("Info"), tr("Hash view not implemented yet")); 191 | } 192 | 193 | buffer.close(); 194 | } 195 | } 196 | } 197 | } 198 | } 199 | } 200 | 201 | void XArchiveWidget::on_lineEditFilter_textChanged(const QString &sString) 202 | { 203 | #if QT_VERSION >= QT_VERSION_CHECK(5, 12, 0) 204 | m_pFilterModel->setFilterRegularExpression(sString); 205 | #else 206 | m_pFilterModel->setFilterRegExp(sString); 207 | #endif 208 | m_pFilterModel->setFilterCaseSensitivity(Qt::CaseInsensitive); 209 | m_pFilterModel->setFilterKeyColumn(0); 210 | } 211 | 212 | void XArchiveWidget::on_tableViewRecords_doubleClicked(const QModelIndex &index) 213 | { 214 | Q_UNUSED(index) 215 | 216 | QModelIndexList listIndexes = ui->tableViewRecords->selectionModel()->selectedIndexes(); 217 | 218 | if (listIndexes.size() > 0) { 219 | hexRecord(); 220 | } 221 | } 222 | 223 | void XArchiveWidget::onTableElement_selected(const QItemSelection &itemSelected, const QItemSelection &itemDeselected) 224 | { 225 | Q_UNUSED(itemSelected) 226 | Q_UNUSED(itemDeselected) 227 | 228 | QModelIndexList listIndexes = ui->tableViewRecords->selectionModel()->selectedIndexes(); 229 | 230 | if (listIndexes.count() > 0) { 231 | QModelIndex sourceIndex = m_pFilterModel->mapToSource(listIndexes.at(0)); 232 | qint32 nRow = sourceIndex.row(); 233 | 234 | if (nRow >= 0 && nRow < m_listRecords.count()) { 235 | m_sCurrentRecordFileName = m_listRecords.at(nRow).spInfo.sRecordName; 236 | m_nCurrentFileSize = m_listRecords.at(nRow).spInfo.nUncompressedSize; 237 | } 238 | } 239 | } 240 | 241 | void XArchiveWidget::registerShortcuts(bool bState) 242 | { 243 | Q_UNUSED(bState) 244 | } 245 | 246 | void XArchiveWidget::loadRecords() 247 | { 248 | if (m_pModel) { 249 | delete m_pModel; 250 | m_pModel = nullptr; 251 | } 252 | 253 | m_pModel = new QStandardItemModel(this); 254 | m_pModel->setHorizontalHeaderLabels(QStringList() << tr("Name") << tr("Size") << tr("Compressed") << tr("Method")); 255 | 256 | if (m_pDevice) { 257 | XArchive *pArchive = new XArchive(m_pDevice); 258 | 259 | // Use new streaming API to get all records 260 | XBinary::UNPACK_STATE state = {}; 261 | QMap mapProperties; 262 | 263 | if (pArchive->initUnpack(&state, mapProperties, nullptr)) { 264 | m_listRecords.clear(); 265 | 266 | while (state.nCurrentIndex < state.nNumberOfRecords) { 267 | XBinary::ARCHIVERECORD record = pArchive->infoCurrent(&state, nullptr); 268 | 269 | QList listItems; 270 | 271 | QString sFileName = record.mapProperties.value(XBinary::FPART_PROP_ORIGINALNAME).toString(); 272 | QStandardItem *pItemName = new QStandardItem(sFileName); 273 | pItemName->setEditable(false); 274 | listItems.append(pItemName); 275 | 276 | qint64 nUncompressedSize = record.mapProperties.value(XBinary::FPART_PROP_UNCOMPRESSEDSIZE).toLongLong(); 277 | QStandardItem *pItemSize = new QStandardItem(QString::number(nUncompressedSize)); 278 | pItemSize->setEditable(false); 279 | pItemSize->setTextAlignment(Qt::AlignRight | Qt::AlignVCenter); 280 | listItems.append(pItemSize); 281 | 282 | qint64 nCompressedSize = record.mapProperties.value(XBinary::FPART_PROP_COMPRESSEDSIZE).toLongLong(); 283 | QStandardItem *pItemCompressed = new QStandardItem(QString::number(nCompressedSize)); 284 | pItemCompressed->setEditable(false); 285 | pItemCompressed->setTextAlignment(Qt::AlignRight | Qt::AlignVCenter); 286 | listItems.append(pItemCompressed); 287 | 288 | XBinary::COMPRESS_METHOD compressMethod = (XBinary::COMPRESS_METHOD)record.mapProperties.value(XBinary::FPART_PROP_COMPRESSMETHOD).toInt(); 289 | QStandardItem *pItemMethod = new QStandardItem(XBinary::compressMethodToString(compressMethod)); 290 | pItemMethod->setEditable(false); 291 | listItems.append(pItemMethod); 292 | 293 | m_pModel->appendRow(listItems); 294 | 295 | // Store record info for later use 296 | XArchive::RECORD oldRecord = {}; 297 | oldRecord.spInfo.sRecordName = sFileName; 298 | oldRecord.spInfo.nUncompressedSize = nUncompressedSize; 299 | oldRecord.spInfo.compressMethod = compressMethod; 300 | oldRecord.nDataOffset = record.nStreamOffset; 301 | oldRecord.nDataSize = record.nStreamSize; 302 | m_listRecords.append(oldRecord); 303 | 304 | pArchive->moveToNext(&state, nullptr); 305 | } 306 | 307 | pArchive->finishUnpack(&state, nullptr); 308 | } 309 | 310 | delete pArchive; 311 | } 312 | 313 | m_pFilterModel->setSourceModel(m_pModel); 314 | ui->tableViewRecords->setModel(m_pFilterModel); 315 | ui->tableViewRecords->setSortingEnabled(true); 316 | 317 | setupTableView(); 318 | } 319 | 320 | void XArchiveWidget::setupTableView() 321 | { 322 | ui->tableViewRecords->setSelectionBehavior(QAbstractItemView::SelectRows); 323 | ui->tableViewRecords->setSelectionMode(QAbstractItemView::SingleSelection); 324 | ui->tableViewRecords->horizontalHeader()->setStretchLastSection(false); 325 | ui->tableViewRecords->horizontalHeader()->setSectionResizeMode(0, QHeaderView::Stretch); 326 | ui->tableViewRecords->horizontalHeader()->setSectionResizeMode(1, QHeaderView::ResizeToContents); 327 | ui->tableViewRecords->horizontalHeader()->setSectionResizeMode(2, QHeaderView::ResizeToContents); 328 | ui->tableViewRecords->horizontalHeader()->setSectionResizeMode(3, QHeaderView::ResizeToContents); 329 | ui->tableViewRecords->verticalHeader()->setVisible(false); 330 | ui->tableViewRecords->verticalHeader()->setDefaultSectionSize(20); 331 | 332 | connect(ui->tableViewRecords->selectionModel(), SIGNAL(selectionChanged(QItemSelection, QItemSelection)), this, 333 | SLOT(onTableElement_selected(QItemSelection, QItemSelection))); 334 | } 335 | -------------------------------------------------------------------------------- /archive_widget.cpp: -------------------------------------------------------------------------------- 1 | /* Copyright (c) 2020-2025 hors 2 | * 3 | * Permission is hereby granted, free of charge, to any person obtaining a copy 4 | * of this software and associated documentation files (the "Software"), to deal 5 | * in the Software without restriction, including without limitation the rights 6 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 7 | * copies of the Software, and to permit persons to whom the Software is 8 | * furnished to do so, subject to the following conditions: 9 | * 10 | * The above copyright notice and this permission notice shall be included in 11 | * all copies or substantial portions of the Software. 12 | * 13 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 14 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 15 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 16 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 17 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 18 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 19 | * SOFTWARE. 20 | */ 21 | #include "archive_widget.h" 22 | 23 | #include "ui_archive_widget.h" 24 | 25 | Archive_widget::Archive_widget(QWidget *pParent) : XShortcutsWidget(pParent), ui(new Ui::Archive_widget) 26 | { 27 | ui->setupUi(this); 28 | 29 | m_pFilterTable = new QSortFilterProxyModel(this); 30 | 31 | ui->comboBoxType->addItem(tr("Tree")); 32 | ui->comboBoxType->addItem(tr("Table")); 33 | 34 | ui->groupBoxFilter->setEnabled(false); 35 | ui->comboBoxType->setCurrentIndex(0); 36 | 37 | m_nCurrentFileSize = 0; 38 | m_bCurrentFileIsRoot = false; 39 | m_type = CreateViewModelProcess::TYPE_UNKNOWN; 40 | } 41 | 42 | void Archive_widget::setFileName(const QString &sFileName, XBinary::FT fileType, const FW_DEF::OPTIONS &options, const QSet &stAvailableOpenFileTypes) 43 | { 44 | setData(CreateViewModelProcess::TYPE_FILE, sFileName, fileType, options, stAvailableOpenFileTypes); 45 | } 46 | 47 | void Archive_widget::setDirectoryName(const QString &sDirectoryName, const FW_DEF::OPTIONS &options, const QSet &stAvailableOpenFileTypes) 48 | { 49 | setData(CreateViewModelProcess::TYPE_DIRECTORY, sDirectoryName, XBinary::FT_UNKNOWN, options, stAvailableOpenFileTypes); 50 | } 51 | 52 | void Archive_widget::setData(CreateViewModelProcess::TYPE type, const QString &sName, XBinary::FT fileType, const FW_DEF::OPTIONS &options, 53 | const QSet &stAvailableOpenFileTypes) 54 | { 55 | m_type = type; 56 | m_sName = sName; 57 | m_options = options; 58 | 59 | m_stAvailableOpenFileTypes = stAvailableOpenFileTypes; 60 | 61 | if (!m_stAvailableOpenFileTypes.count()) { 62 | // TODO more 63 | // TODO Check mb Archives 64 | // TODO APK, JAR, ZIP, IPA, NPM 65 | m_stAvailableOpenFileTypes.insert(XBinary::FT_MSDOS); 66 | m_stAvailableOpenFileTypes.insert(XBinary::FT_NE); 67 | m_stAvailableOpenFileTypes.insert(XBinary::FT_LE); 68 | m_stAvailableOpenFileTypes.insert(XBinary::FT_LX); 69 | m_stAvailableOpenFileTypes.insert(XBinary::FT_PE); 70 | m_stAvailableOpenFileTypes.insert(XBinary::FT_ELF); 71 | m_stAvailableOpenFileTypes.insert(XBinary::FT_DEX); 72 | m_stAvailableOpenFileTypes.insert(XBinary::FT_MACHO); 73 | m_stAvailableOpenFileTypes.insert(XBinary::FT_MACHOFAT); 74 | m_stAvailableOpenFileTypes.insert(XBinary::FT_BMP); 75 | m_stAvailableOpenFileTypes.insert(XBinary::FT_PNG); 76 | m_stAvailableOpenFileTypes.insert(XBinary::FT_JPEG); 77 | m_stAvailableOpenFileTypes.insert(XBinary::FT_GIF); 78 | m_stAvailableOpenFileTypes.insert(XBinary::FT_TIFF); 79 | m_stAvailableOpenFileTypes.insert(XBinary::FT_TEXT); 80 | m_stAvailableOpenFileTypes.insert(XBinary::FT_ANDROIDXML); 81 | } 82 | 83 | ui->tableViewArchive->setSortingEnabled(false); 84 | 85 | QAbstractItemModel *pOldTreeModel = ui->treeViewArchive->model(); 86 | QStandardItemModel *pNewTreeModel = nullptr; 87 | 88 | QAbstractItemModel *pOldTableModel = m_pFilterTable->sourceModel(); 89 | QStandardItemModel *pNewTableModel = nullptr; 90 | 91 | m_pFilterTable->setSourceModel(0); 92 | ui->tableViewArchive->setModel(0); 93 | 94 | ui->comboBoxType->setCurrentIndex(0); 95 | ui->lineEditFilter->clear(); 96 | 97 | QSet stFilterFileTypes; 98 | 99 | if (m_options.bFilter) { 100 | stFilterFileTypes = m_stAvailableOpenFileTypes; 101 | } 102 | 103 | m_listViewRecords.clear(); 104 | 105 | DialogCreateViewModel dialogCreateViewModel(XOptions::getMainWidget(this)); 106 | dialogCreateViewModel.setData(type, sName, fileType, &m_listRecords, &pNewTreeModel, &pNewTableModel, stFilterFileTypes, &m_listViewRecords); 107 | 108 | dialogCreateViewModel.showDialogDelay(); 109 | 110 | ui->treeViewArchive->setModel(pNewTreeModel); 111 | 112 | ui->treeViewArchive->header()->setSectionResizeMode(0, QHeaderView::Stretch); 113 | ui->treeViewArchive->header()->setSectionResizeMode(1, QHeaderView::Interactive); 114 | 115 | m_pFilterTable->setSourceModel(pNewTableModel); 116 | ui->tableViewArchive->setModel(m_pFilterTable); // TODO XTableView 117 | 118 | ui->tableViewArchive->horizontalHeader()->setSectionResizeMode(0, QHeaderView::Interactive); 119 | ui->tableViewArchive->horizontalHeader()->setSectionResizeMode(1, QHeaderView::Stretch); 120 | ui->tableViewArchive->horizontalHeader()->setSectionResizeMode(2, QHeaderView::Interactive); 121 | 122 | deleteOldAbstractModel(&pOldTreeModel); 123 | deleteOldAbstractModel(&pOldTableModel); 124 | 125 | ui->tableViewArchive->setSortingEnabled(true); 126 | ui->tableViewArchive->sortByColumn(0, Qt::AscendingOrder); 127 | 128 | ui->tableViewArchive->setColumnWidth(0, 20); // TODO consts !!! 129 | 130 | ui->treeViewArchive->expand(pNewTreeModel->index(0, 0)); 131 | 132 | connect(ui->treeViewArchive->selectionModel(), SIGNAL(selectionChanged(QItemSelection, QItemSelection)), this, 133 | SLOT(onTreeElement_selected(QItemSelection, QItemSelection))); 134 | connect(ui->tableViewArchive->selectionModel(), SIGNAL(selectionChanged(QItemSelection, QItemSelection)), this, 135 | SLOT(onTableElement_selected(QItemSelection, QItemSelection))); 136 | 137 | if (m_options.bFilter) { 138 | ui->comboBoxType->setCurrentIndex(1); // TODO enum !!! 139 | 140 | if (m_listRecords.count()) { 141 | ui->tableViewArchive->setCurrentIndex(ui->tableViewArchive->model()->index(0, 0)); 142 | } 143 | } 144 | } 145 | 146 | QString Archive_widget::getCurrentRecordFileName() 147 | { 148 | return m_sCurrentRecordFileName; 149 | } 150 | 151 | QList Archive_widget::getRecordsByFileType(XBinary::FT fileType) 152 | { 153 | QList listResult; 154 | 155 | qint32 nNumberOfRecords = m_listViewRecords.count(); 156 | 157 | for (qint32 i = 0; i < nNumberOfRecords; i++) { 158 | if (XBinary::checkFileType(fileType, m_listViewRecords.at(i).ft)) { 159 | listResult.append(m_listViewRecords.at(i)); 160 | } 161 | } 162 | 163 | return listResult; 164 | } 165 | 166 | void Archive_widget::adjustView() 167 | { 168 | } 169 | 170 | void Archive_widget::reloadData(bool bSaveSelection) 171 | { 172 | Q_UNUSED(bSaveSelection) 173 | 174 | // TODO 175 | } 176 | 177 | Archive_widget::~Archive_widget() 178 | { 179 | delete ui; 180 | } 181 | 182 | void Archive_widget::on_treeViewArchive_customContextMenuRequested(const QPoint &pos) 183 | { 184 | QModelIndexList listIndexes = ui->treeViewArchive->selectionModel()->selectedIndexes(); 185 | 186 | if (listIndexes.size() > 0) { 187 | showContext(m_sCurrentRecordFileName, m_bCurrentFileIsRoot, ui->treeViewArchive->viewport()->mapToGlobal(pos)); 188 | } 189 | } 190 | 191 | void Archive_widget::on_tableViewArchive_customContextMenuRequested(const QPoint &pos) 192 | { 193 | QModelIndexList listIndexes = ui->tableViewArchive->selectionModel()->selectedIndexes(); 194 | 195 | if (listIndexes.size() > 0) { 196 | showContext(m_sCurrentRecordFileName, m_bCurrentFileIsRoot, ui->tableViewArchive->viewport()->mapToGlobal(pos)); 197 | } 198 | } 199 | 200 | void Archive_widget::showContext(const QString &sRecordFileName, bool bIsRoot, QPoint point) 201 | { 202 | if (sRecordFileName != "") { 203 | QMenu contextMenu(this); // TODO 204 | 205 | QAction actionOpen(tr("Open"), this); 206 | 207 | if (!m_options.bNoWindowOpen) { 208 | if (isOpenAvailable(sRecordFileName, bIsRoot)) { 209 | actionOpen.setShortcut(getShortcuts()->getShortcut(X_ID_ARCHIVE_OPEN)); 210 | connect(&actionOpen, SIGNAL(triggered()), this, SLOT(openRecord())); 211 | contextMenu.addAction(&actionOpen); 212 | } 213 | } 214 | 215 | QAction actionScan(tr("Scan"), this); 216 | actionScan.setShortcut(getShortcuts()->getShortcut(X_ID_ARCHIVE_SCAN)); 217 | connect(&actionScan, SIGNAL(triggered()), this, SLOT(scanRecord())); 218 | contextMenu.addAction(&actionScan); 219 | 220 | QAction actionHex(tr("Hex"), this); 221 | actionHex.setShortcut(getShortcuts()->getShortcut(X_ID_ARCHIVE_HEX)); 222 | connect(&actionHex, SIGNAL(triggered()), this, SLOT(hexRecord())); 223 | contextMenu.addAction(&actionHex); 224 | 225 | QAction actionStrings(tr("Strings"), this); 226 | actionStrings.setShortcut(getShortcuts()->getShortcut(X_ID_ARCHIVE_STRINGS)); 227 | connect(&actionStrings, SIGNAL(triggered()), this, SLOT(stringsRecord())); 228 | contextMenu.addAction(&actionStrings); 229 | 230 | QAction actionEntropy(tr("Entropy"), this); 231 | actionEntropy.setShortcut(getShortcuts()->getShortcut(X_ID_ARCHIVE_ENTROPY)); 232 | connect(&actionEntropy, SIGNAL(triggered()), this, SLOT(entropyRecord())); 233 | contextMenu.addAction(&actionEntropy); 234 | 235 | QAction actionHash(tr("Hash"), this); 236 | actionHash.setShortcut(getShortcuts()->getShortcut(X_ID_ARCHIVE_HASH)); 237 | connect(&actionHash, SIGNAL(triggered()), this, SLOT(hashRecord())); 238 | contextMenu.addAction(&actionHash); 239 | 240 | QMenu menuCopy(tr("Copy"), this); 241 | QAction actionCopyFilename(tr("File name"), this); 242 | actionCopyFilename.setShortcut(getShortcuts()->getShortcut(X_ID_ARCHIVE_COPY_FILENAME)); 243 | connect(&actionCopyFilename, SIGNAL(triggered()), this, SLOT(copyFileName())); 244 | menuCopy.addAction(&actionCopyFilename); 245 | contextMenu.addMenu(&menuCopy); 246 | 247 | QAction actionDump(tr("Dump to file"), this); 248 | 249 | if (!bIsRoot) { 250 | actionDump.setShortcut(getShortcuts()->getShortcut(X_ID_ARCHIVE_DUMPTOFILE)); 251 | connect(&actionDump, SIGNAL(triggered()), this, SLOT(dumpRecord())); 252 | contextMenu.addAction(&actionDump); 253 | } 254 | 255 | // contextMenu.addMenu(getShortcuts()->getRowCopyMenu(this, ui->tableView_XXXX)); 256 | 257 | contextMenu.exec(point); 258 | } 259 | } 260 | 261 | bool Archive_widget::isOpenAvailable(const QString &sRecordFileName, bool bIsRoot) 262 | { 263 | bool bResult = false; 264 | 265 | QSet stFileTypes; 266 | 267 | if (bIsRoot || (m_type == CreateViewModelProcess::TYPE_DIRECTORY)) { 268 | stFileTypes = XFormats::getFileTypes(sRecordFileName, true); 269 | } else { 270 | XArchive::RECORD record = XArchive::getArchiveRecord(sRecordFileName, &m_listRecords); 271 | 272 | QByteArray baData = XArchives::decompress(m_sName, &record, nullptr, 0, 0x200); 273 | stFileTypes = XFormats::getFileTypes(&baData, true); 274 | } 275 | 276 | if (XBinary::isFileTypePresent(&stFileTypes, &m_stAvailableOpenFileTypes)) { 277 | bResult = true; 278 | } 279 | 280 | return bResult; 281 | } 282 | 283 | void Archive_widget::openRecord() 284 | { 285 | if (!m_options.bNoWindowOpen) { 286 | if (isOpenAvailable(m_sCurrentRecordFileName, m_bCurrentFileIsRoot)) { 287 | handleAction(ACTION_OPEN); 288 | } else { 289 | handleAction(ACTION_HEX); 290 | } 291 | } 292 | // TODO open for m_options.bNoWindowOpen 293 | } 294 | 295 | void Archive_widget::scanRecord() 296 | { 297 | handleAction(ACTION_SCAN); 298 | } 299 | 300 | void Archive_widget::hexRecord() 301 | { 302 | handleAction(ACTION_HEX); 303 | } 304 | 305 | void Archive_widget::stringsRecord() 306 | { 307 | handleAction(ACTION_STRINGS); 308 | } 309 | 310 | void Archive_widget::entropyRecord() 311 | { 312 | handleAction(ACTION_ENTROPY); 313 | } 314 | 315 | void Archive_widget::hashRecord() 316 | { 317 | handleAction(ACTION_HASH); 318 | } 319 | 320 | void Archive_widget::copyFileName() 321 | { 322 | handleAction(ACTION_COPYFILENAME); 323 | } 324 | 325 | void Archive_widget::dumpRecord() 326 | { 327 | handleAction(ACTION_DUMP); 328 | } 329 | 330 | void Archive_widget::handleAction(Archive_widget::ACTION action) 331 | { 332 | qint64 nSize = m_nCurrentFileSize; 333 | bool bIsRoot = m_bCurrentFileIsRoot; 334 | QString sRecordFileName = m_sCurrentRecordFileName; 335 | 336 | if (sRecordFileName != "") { 337 | if (bIsRoot || (m_type == CreateViewModelProcess::TYPE_DIRECTORY)) { 338 | if (action == ACTION_OPEN) { 339 | _handleActionOpenFile(sRecordFileName, sRecordFileName, true); 340 | } else if (action == ACTION_COPYFILENAME) { 341 | QGuiApplication::clipboard()->setText(sRecordFileName); 342 | } else { 343 | QFile file; 344 | 345 | file.setFileName(sRecordFileName); 346 | 347 | if (XBinary::tryToOpen(&file)) { 348 | _handleActionDevice(action, &file); 349 | 350 | file.close(); 351 | } 352 | } 353 | } else { 354 | XArchive::RECORD record = XArchive::getArchiveRecord(sRecordFileName, &m_listRecords); 355 | 356 | if (action == ACTION_OPEN) { 357 | QTemporaryFile fileTemp; 358 | 359 | if (fileTemp.open()) { 360 | QString sTempFileName = fileTemp.fileName(); 361 | 362 | DialogUnpackFile dialogUnpackFile(XOptions::getMainWidget(this)); 363 | 364 | dialogUnpackFile.setData(m_sName, &record, sTempFileName); 365 | 366 | // TODO timer 367 | if (dialogUnpackFile.exec() == QDialog::Accepted) { 368 | _handleActionOpenFile(sTempFileName, record.spInfo.sRecordName, false); 369 | } 370 | } 371 | } else if (action == ACTION_COPYFILENAME) { 372 | QGuiApplication::clipboard()->setText(record.spInfo.sRecordName); 373 | } else if (action == ACTION_DUMP) { 374 | QString sSaveFileName = QFileInfo(m_sName).absolutePath() + QDir::separator() + QFileInfo(record.spInfo.sRecordName).fileName(); 375 | 376 | sSaveFileName = QFileDialog::getSaveFileName(this, tr("Save file"), sSaveFileName, QFileInfo(record.spInfo.sRecordName).completeSuffix()); 377 | 378 | if (sSaveFileName != "") { 379 | DialogUnpackFile dialogUnpackFile(XOptions::getMainWidget(this)); 380 | 381 | dialogUnpackFile.setData(m_sName, &record, sSaveFileName); 382 | 383 | // TODO timer 384 | if (dialogUnpackFile.exec() != QDialog::Accepted) { 385 | QMessageBox::critical(XOptions::getMainWidget(this), tr("Error"), tr("Cannot save file")); 386 | } 387 | } 388 | } else { 389 | if (nSize <= XArchive::getCompressBufferSize()) { 390 | QByteArray baData = XArchives::decompress(m_sName, &record); 391 | 392 | QBuffer buffer; 393 | 394 | buffer.setBuffer(&baData); 395 | 396 | if (buffer.open(QIODevice::ReadOnly)) { 397 | _handleActionDevice(action, &buffer); 398 | 399 | buffer.close(); 400 | } 401 | } else { 402 | QTemporaryFile fileTemp; 403 | 404 | if (fileTemp.open()) { 405 | QString sTempFileName = fileTemp.fileName(); 406 | 407 | DialogUnpackFile dialogUnpackFile(this); 408 | dialogUnpackFile.setGlobal(getShortcuts(), getGlobalOptions()); 409 | dialogUnpackFile.setData(m_sName, &record, sTempFileName); 410 | 411 | if (dialogUnpackFile.exec() == QDialog::Accepted) { 412 | QFile file; 413 | 414 | file.setFileName(sTempFileName); 415 | 416 | if (file.open(QIODevice::ReadOnly)) { 417 | _handleActionDevice(action, &file); 418 | 419 | file.close(); 420 | } 421 | } 422 | } 423 | } 424 | } 425 | } 426 | } 427 | } 428 | 429 | void Archive_widget::_handleActionDevice(Archive_widget::ACTION action, QIODevice *pDevice) 430 | { 431 | if (action == ACTION_SCAN) { 432 | DialogNFDScan dialogStaticScan(this); 433 | dialogStaticScan.setData(pDevice, true, XBinary::FT_UNKNOWN); 434 | 435 | dialogStaticScan.exec(); 436 | } else if (action == ACTION_HEX) { 437 | XHexViewWidget::OPTIONS options = {}; 438 | 439 | // TODO options 440 | 441 | DialogHexView dialogHexView(this); 442 | dialogHexView.setGlobal(getShortcuts(), getGlobalOptions()); 443 | dialogHexView.setData(pDevice, options); 444 | // TODO XINfoDB !!! 445 | 446 | dialogHexView.exec(); 447 | } else if (action == ACTION_STRINGS) { 448 | SearchStringsWidget::OPTIONS stringsOptions = {}; 449 | stringsOptions.bMenu_Hex = true; 450 | stringsOptions.bMenu_Demangle = true; 451 | stringsOptions.bAnsi = true; 452 | // stringsOptions.bUTF8 = false; 453 | stringsOptions.bUnicode = true; 454 | stringsOptions.bNullTerminated = false; 455 | 456 | DialogSearchStrings dialogSearchStrings(this); 457 | dialogSearchStrings.setGlobal(getShortcuts(), getGlobalOptions()); 458 | dialogSearchStrings.setData(pDevice, XBinary::FT_UNKNOWN, stringsOptions, true); 459 | 460 | dialogSearchStrings.exec(); 461 | } else if (action == ACTION_ENTROPY) { 462 | DialogEntropy dialogEntropy(this); 463 | dialogEntropy.setGlobal(getShortcuts(), getGlobalOptions()); 464 | dialogEntropy.setData(pDevice); 465 | 466 | dialogEntropy.exec(); 467 | } else if (action == ACTION_HASH) { 468 | DialogHash dialogHash(this); 469 | dialogHash.setGlobal(getShortcuts(), getGlobalOptions()); 470 | dialogHash.setData(pDevice, XBinary::FT_UNKNOWN); 471 | 472 | dialogHash.exec(); 473 | } 474 | } 475 | 476 | void Archive_widget::_handleActionOpenFile(const QString &sFileName, const QString &sTitle, bool bReadWrite) 477 | { 478 | QSet stFileTypes = XFormats::getFileTypes(sFileName, true); 479 | 480 | if (stFileTypes.contains(XBinary::FT_PNG) || stFileTypes.contains(XBinary::FT_JPEG) || stFileTypes.contains(XBinary::FT_TIFF) || 481 | stFileTypes.contains(XBinary::FT_GIF) || stFileTypes.contains(XBinary::FT_BMP)) { 482 | DialogShowImage dialogShowImage(this, sFileName, sTitle); 483 | 484 | dialogShowImage.exec(); 485 | } else if (stFileTypes.contains(XBinary::FT_TEXT)) { 486 | DialogTextInfo dialogTextInfo(this); 487 | dialogTextInfo.setTitle(sTitle); 488 | dialogTextInfo.setWrap(false); 489 | 490 | dialogTextInfo.setFileName(sFileName); 491 | 492 | dialogTextInfo.exec(); 493 | } else if (stFileTypes.contains(XBinary::FT_ANDROIDXML)) { 494 | QString sString = XAndroidBinary::getDecoded(sFileName, nullptr); 495 | 496 | DialogTextInfo dialogTextInfo(this); 497 | dialogTextInfo.setTitle(sTitle); 498 | dialogTextInfo.setWrap(false); 499 | 500 | dialogTextInfo.setText(sString); 501 | 502 | dialogTextInfo.exec(); 503 | } else if (stFileTypes.contains(XBinary::FT_MSDOS) || stFileTypes.contains(XBinary::FT_NE) || stFileTypes.contains(XBinary::FT_LE) || 504 | stFileTypes.contains(XBinary::FT_LX) || stFileTypes.contains(XBinary::FT_PE) || stFileTypes.contains(XBinary::FT_ELF) || 505 | stFileTypes.contains(XBinary::FT_MACHO) || stFileTypes.contains(XBinary::FT_DEX)) { 506 | QFile file; 507 | 508 | file.setFileName(sFileName); 509 | 510 | bool bOpen = false; 511 | 512 | if (bReadWrite) { 513 | bOpen = XBinary::tryToOpen(&file); 514 | } else { 515 | bOpen = file.open(QIODevice::ReadOnly); 516 | } 517 | 518 | if (bOpen) { 519 | FW_DEF::OPTIONS options = m_options; // TODO options from setData 520 | options.sTitle = sTitle; 521 | 522 | if (stFileTypes.contains(XBinary::FT_PE)) { 523 | options.nStartType = SPE::TYPE_IMAGE_FILE_HEADER; 524 | options.nImageBase = -1; 525 | 526 | DialogPE dialogPE(this); 527 | dialogPE.setGlobal(getShortcuts(), getGlobalOptions()); 528 | dialogPE.setData(&file, options); 529 | 530 | dialogPE.exec(); 531 | } else if (stFileTypes.contains(XBinary::FT_LE)) { 532 | options.nStartType = SLE::TYPE_VXD_HEADER; 533 | options.nImageBase = -1; 534 | 535 | DialogLE dialogLE(this); 536 | dialogLE.setGlobal(getShortcuts(), getGlobalOptions()); 537 | dialogLE.setData(&file, options); 538 | 539 | dialogLE.exec(); 540 | } else if (stFileTypes.contains(XBinary::FT_NE)) { 541 | options.nStartType = SNE::TYPE_OS2_HEADER; 542 | options.nImageBase = -1; 543 | 544 | DialogNE dialogNE(this); 545 | dialogNE.setGlobal(getShortcuts(), getGlobalOptions()); 546 | dialogNE.setData(&file, options); 547 | 548 | dialogNE.exec(); 549 | } else if (stFileTypes.contains(XBinary::FT_MSDOS)) { 550 | options.nStartType = SMSDOS::TYPE_DOS_HEADER; 551 | options.nImageBase = -1; 552 | 553 | DialogMSDOS dialogMSDOS(this); 554 | dialogMSDOS.setGlobal(getShortcuts(), getGlobalOptions()); 555 | dialogMSDOS.setData(&file, options); 556 | 557 | dialogMSDOS.exec(); 558 | } else if (stFileTypes.contains(XBinary::FT_ELF)) { 559 | options.nStartType = SELF::TYPE_Elf_Ehdr; 560 | options.nImageBase = -1; 561 | 562 | DialogELF dialogELF(this); 563 | dialogELF.setGlobal(getShortcuts(), getGlobalOptions()); 564 | dialogELF.setData(&file, options); 565 | 566 | dialogELF.exec(); 567 | } else if (stFileTypes.contains(XBinary::FT_MACHO)) { 568 | options.nStartType = SMACH::TYPE_mach_header; 569 | options.nImageBase = -1; 570 | 571 | DialogMACH dialogMACH(this); 572 | dialogMACH.setGlobal(getShortcuts(), getGlobalOptions()); 573 | dialogMACH.setData(&file, options); 574 | 575 | dialogMACH.exec(); 576 | } else if (stFileTypes.contains(XBinary::FT_DEX)) { 577 | options.nStartType = SDEX::TYPE_HEADER; 578 | options.nImageBase = -1; 579 | 580 | DialogDEX dialogDEX(this); 581 | dialogDEX.setGlobal(getShortcuts(), getGlobalOptions()); 582 | dialogDEX.setData(&file, options); 583 | 584 | dialogDEX.exec(); 585 | } 586 | 587 | file.close(); 588 | } 589 | } 590 | } 591 | 592 | void Archive_widget::on_comboBoxType_currentIndexChanged(int nIndex) 593 | { 594 | ui->stackedWidgetArchive->setCurrentIndex(nIndex); 595 | 596 | ui->groupBoxFilter->setEnabled(nIndex); 597 | } 598 | 599 | void Archive_widget::on_lineEditFilter_textChanged(const QString &sString) 600 | { 601 | #if QT_VERSION >= QT_VERSION_CHECK(5, 12, 0) 602 | m_pFilterTable->setFilterRegularExpression(sString); 603 | #else 604 | m_pFilterTable->setFilterRegExp(sString); 605 | #endif 606 | m_pFilterTable->setFilterCaseSensitivity(Qt::CaseInsensitive); 607 | m_pFilterTable->setFilterKeyColumn(1); 608 | } 609 | 610 | void Archive_widget::on_treeViewArchive_doubleClicked(const QModelIndex &index) 611 | { 612 | Q_UNUSED(index) 613 | 614 | QModelIndexList listIndexes = ui->treeViewArchive->selectionModel()->selectedIndexes(); 615 | 616 | if (listIndexes.size() > 0) { 617 | openRecord(); 618 | } 619 | } 620 | 621 | void Archive_widget::on_tableViewArchive_doubleClicked(const QModelIndex &index) 622 | { 623 | Q_UNUSED(index) 624 | 625 | QModelIndexList listIndexes = ui->tableViewArchive->selectionModel()->selectedIndexes(); 626 | 627 | if (listIndexes.size() > 0) { 628 | openRecord(); 629 | } 630 | } 631 | 632 | void Archive_widget::onTreeElement_selected(const QItemSelection &itemSelected, const QItemSelection &itemDeselected) 633 | { 634 | Q_UNUSED(itemSelected) 635 | Q_UNUSED(itemDeselected) 636 | 637 | QModelIndexList listIndexes = ui->treeViewArchive->selectionModel()->selectedIndexes(); 638 | 639 | if (listIndexes.count() > 0) { 640 | QModelIndex _index = listIndexes.at(0); 641 | 642 | m_sCurrentRecordFileName = ui->treeViewArchive->model()->data(_index, Qt::UserRole + CreateViewModelProcess::UR_PATH).toString(); 643 | m_bCurrentFileIsRoot = ui->treeViewArchive->model()->data(_index, Qt::UserRole + CreateViewModelProcess::UR_ISROOT).toBool(); 644 | m_nCurrentFileSize = ui->treeViewArchive->model()->data(_index, Qt::UserRole + CreateViewModelProcess::UR_SIZE).toLongLong(); 645 | } 646 | } 647 | 648 | void Archive_widget::registerShortcuts(bool bState) 649 | { 650 | Q_UNUSED(bState) 651 | 652 | // TODO !!! 653 | } 654 | 655 | void Archive_widget::onTableElement_selected(const QItemSelection &itemSelected, const QItemSelection &itemDeselected) 656 | { 657 | Q_UNUSED(itemSelected) 658 | Q_UNUSED(itemDeselected) 659 | 660 | QModelIndexList listIndexes = ui->tableViewArchive->selectionModel()->selectedIndexes(); 661 | 662 | if (listIndexes.count() > 0) { 663 | QModelIndex _index = listIndexes.at(0); 664 | 665 | m_sCurrentRecordFileName = ui->tableViewArchive->model()->data(_index, Qt::UserRole + CreateViewModelProcess::UR_PATH).toString(); 666 | m_bCurrentFileIsRoot = ui->tableViewArchive->model()->data(_index, Qt::UserRole + CreateViewModelProcess::UR_ISROOT).toBool(); 667 | m_nCurrentFileSize = ui->tableViewArchive->model()->data(_index, Qt::UserRole + CreateViewModelProcess::UR_SIZE).toLongLong(); 668 | } 669 | } 670 | --------------------------------------------------------------------------------