├── .github └── FUNDING.yml ├── .gitignore ├── CMakeLists.txt ├── DEPENDENCIES.md ├── LICENSE ├── README.md ├── assets ├── addressEdit.jpg ├── addressSearchV.jpg ├── checkBoxLog.jpg ├── editValueAddress.jpg ├── editedLog.jpg ├── editedMP.jpg ├── kill.jpg ├── log.jpg ├── maProc.png ├── pageLog.jpg ├── pid.jpg ├── search.jpg ├── sstopTerminal.jpg ├── stopp.jpg └── viewAddress.jpg └── src ├── dirwindow.cpp ├── dirwindow.hpp ├── gui ├── about.ui ├── assets │ ├── about.png │ ├── clean.png │ ├── close.png │ ├── edit.png │ ├── help.png │ ├── hex.png │ ├── kill.png │ ├── maProc.png │ ├── new.png │ ├── pid_proc.png │ ├── play.png │ ├── rpid.png │ ├── save.png │ ├── search.png │ ├── show.png │ └── stop.png ├── dirwindow.ui ├── mainwindow.ui └── style │ ├── dark.css │ └── light.css ├── include ├── data │ ├── elf │ │ └── structs.hpp │ ├── erros.hpp │ ├── map │ │ └── structs.hpp │ └── win │ │ └── structs.hpp ├── elf │ ├── relf.cpp │ └── relf.hpp ├── fd │ ├── filedescriptor.cpp │ └── filedescriptor.hpp ├── map │ ├── pmap.cpp │ ├── pmap.hpp │ ├── proclib.cpp │ └── proclib.hpp ├── memory │ ├── arena.cpp │ └── arena.hpp └── ps │ ├── ps.cpp │ └── ps.hpp ├── main.cpp ├── mainwindow.cpp ├── mainwindow.hpp ├── qhexview.cpp └── qhexview.hpp /.github/FUNDING.yml: -------------------------------------------------------------------------------- 1 | custom: ['http://menteb.in/apoie'] 2 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | build 2 | -------------------------------------------------------------------------------- /CMakeLists.txt: -------------------------------------------------------------------------------- 1 | cmake_minimum_required(VERSION 3.5) 2 | 3 | project(maProc VERSION 0.1 LANGUAGES CXX) 4 | 5 | set(CMAKE_INCLUDE_CURRENT_DIR ON) 6 | 7 | set(CMAKE_AUTOUIC ON) 8 | set(CMAKE_AUTOMOC ON) 9 | set(CMAKE_AUTORCC ON) 10 | set(OPTIMIZATIONS ON) 11 | 12 | set(CMAKE_CXX_STANDARD 11) 13 | set(CMAKE_CXX_STANDARD_REQUIRED ON) 14 | 15 | find_package(QT NAMES Qt6 Qt5 COMPONENTS Widgets REQUIRED) 16 | find_package(Qt${QT_VERSION_MAJOR} COMPONENTS Widgets REQUIRED) 17 | 18 | set(CMAKE_CXX_FLAGS " ") 19 | 20 | if(OPTIMIZATIONS) 21 | set(CMAKE_CXX_FLAGS "-ftree-vectorize -march=native -fdelete-dead-exceptions -mavx -fno-stack-protector -march=native -O2 -Os -fdelete-null-pointer-checks") 22 | set(DEBUGGER OFF) 23 | endif() 24 | 25 | if(DEBUGGER) 26 | set(CMAKE_CXX_FLAGS "-g -gdwarf -gdwarf-version") 27 | endif() 28 | 29 | set(PROJECT_SOURCES 30 | 31 | src/include/elf/relf.cpp 32 | src/include/elf/relf.hpp 33 | 34 | src/main.cpp 35 | src/mainwindow.cpp 36 | 37 | src/include/ps/ps.hpp 38 | src/include/ps/ps.cpp 39 | 40 | src/include/memory/arena.hpp 41 | src/include/memory/arena.cpp 42 | 43 | src/include/fd/filedescriptor.hpp 44 | src/include/fd/filedescriptor.cpp 45 | 46 | src/include/map/pmap.hpp 47 | src/include/map/pmap.cpp 48 | 49 | src/include/map/proclib.hpp 50 | src/include/map/proclib.cpp 51 | 52 | src/qhexview.cpp 53 | src/qhexview.hpp 54 | 55 | src/mainwindow.hpp 56 | src/gui/mainwindow.ui 57 | src/gui/about.ui 58 | 59 | src/dirwindow.hpp 60 | src/dirwindow.cpp 61 | src/gui/dirwindow.ui 62 | ) 63 | add_executable(maProc 64 | ${PROJECT_SOURCES} 65 | ) 66 | 67 | if(${QT_VERSION_MAJOR} GREATER_EQUAL 6) 68 | qt_add_executable(maProc 69 | MANUAL_FINALIZATION 70 | ${PROJECT_SOURCES} 71 | ) 72 | endif() 73 | 74 | target_link_libraries(maProc PRIVATE Qt${QT_VERSION_MAJOR}::Widgets) 75 | 76 | set_target_properties(maProc PROPERTIES 77 | MACOSX_BUNDLE_GUI_IDENTIFIER my.example.com 78 | MACOSX_BUNDLE_BUNDLE_VERSION ${PROJECT_VERSION} 79 | MACOSX_BUNDLE_SHORT_VERSION_STRING ${PROJECT_VERSION_MAJOR}.${PROJECT_VERSION_MINOR} 80 | ) 81 | 82 | if(QT_VERSION_MAJOR EQUAL 6) 83 | qt_finalize_executable(maProc) 84 | endif() -------------------------------------------------------------------------------- /DEPENDENCIES.md: -------------------------------------------------------------------------------- 1 | # Dependencies 2 | 3 | I will just quote the dependencies of some distros, just follow the steps below 4 | 5 | ## Debian (Kali linux, MX linux, Linux Mint...) 6 | 7 | Qt creator and Build Essential 8 | * apt-get install qtbase5-dev qtdeclarative5-dev # qt-creator 9 | * apt-get install build-essential # gcc cmake... 10 | 11 | ## AUR (Manjaro, Arch...) 12 | 13 | Qt creator and Build Essential 14 | * pacman -Sys qt5-base qt5-declarative # qt-creator 15 | * pacman -Sys build-essential # gcc cmake... 16 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | BSD 2-Clause License 2 | 3 | Copyright (c) 2022, Mente Binária 4 | All rights reserved. 5 | 6 | Redistribution and use in source and binary forms, with or without 7 | modification, are permitted provided that the following conditions are met: 8 | 9 | 1. Redistributions of source code must retain the above copyright notice, this 10 | list of conditions and the following disclaimer. 11 | 12 | 2. Redistributions in binary form must reproduce the above copyright notice, 13 | this list of conditions and the following disclaimer in the documentation 14 | and/or other materials provided with the distribution. 15 | 16 | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 17 | AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 18 | IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 19 | DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE 20 | FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 21 | DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR 22 | SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER 23 | CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, 24 | OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 25 | OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 26 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # maProc 🐉 2 | As the name maProc informs, it will map processes in linux, being able to check a process's stack/heap, being able to change the memory with write permission, you can manipulate the process by sending a SIGNAL and can stop or pause it process. 3 | 4 | 5 | # Infos ℹ️ 6 | > Made in C++ lang 7 | 8 | > Maproc will easily change the memory without depending on ptrace, however we will depend on the support of the system to contain the pseudo directory `/mem`, otherwise reading and writing in memory will not be possible,we intend to implement it with ptrace in the future. 9 | 10 | > [License](LICENSE) BSD 2-Clause 11 | 12 | > [DEPENDENCIES](DEPENDENCIES.md) 13 | 14 | # About ©️ 15 | we will make the maProc libs available in the following organization [CoffeeCode](https://github.com/0xc0ffeec0de), create your own maProc. 16 | The project's main creators are [Mob](https://github.com/VitorMob), [Buzzer](https://github.com/AandersonL) with all copyrights to Mente Binária. 17 | 18 | 19 | # Features 🔥 20 | 21 | * Manipulate process 22 | * Mapper memory process 23 | * Elf Header Parser 24 | 25 | # Compile 🖨️ 26 | 27 | > Commands 28 | 29 | cd maProc 30 | mkdir build 31 | cd build 32 | cmake .. 33 | make 34 | 35 | 36 | # Pages 📄 37 | 38 | * [Home](https://github.com/mentebinaria/maProc/wiki) 39 | * [Help](https://github.com/mentebinaria/maProc/wiki/Help) 40 | 41 | 42 | 43 | # Screenshots 🎦 44 | 45 | ![maproc](assets/maProc.png) 46 | -------------------------------------------------------------------------------- /assets/addressEdit.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mentebinaria/maProc/dee8d4c17bc7f236d98e3f734fd61c35502b7137/assets/addressEdit.jpg -------------------------------------------------------------------------------- /assets/addressSearchV.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mentebinaria/maProc/dee8d4c17bc7f236d98e3f734fd61c35502b7137/assets/addressSearchV.jpg -------------------------------------------------------------------------------- /assets/checkBoxLog.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mentebinaria/maProc/dee8d4c17bc7f236d98e3f734fd61c35502b7137/assets/checkBoxLog.jpg -------------------------------------------------------------------------------- /assets/editValueAddress.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mentebinaria/maProc/dee8d4c17bc7f236d98e3f734fd61c35502b7137/assets/editValueAddress.jpg -------------------------------------------------------------------------------- /assets/editedLog.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mentebinaria/maProc/dee8d4c17bc7f236d98e3f734fd61c35502b7137/assets/editedLog.jpg -------------------------------------------------------------------------------- /assets/editedMP.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mentebinaria/maProc/dee8d4c17bc7f236d98e3f734fd61c35502b7137/assets/editedMP.jpg -------------------------------------------------------------------------------- /assets/kill.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mentebinaria/maProc/dee8d4c17bc7f236d98e3f734fd61c35502b7137/assets/kill.jpg -------------------------------------------------------------------------------- /assets/log.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mentebinaria/maProc/dee8d4c17bc7f236d98e3f734fd61c35502b7137/assets/log.jpg -------------------------------------------------------------------------------- /assets/maProc.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mentebinaria/maProc/dee8d4c17bc7f236d98e3f734fd61c35502b7137/assets/maProc.png -------------------------------------------------------------------------------- /assets/pageLog.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mentebinaria/maProc/dee8d4c17bc7f236d98e3f734fd61c35502b7137/assets/pageLog.jpg -------------------------------------------------------------------------------- /assets/pid.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mentebinaria/maProc/dee8d4c17bc7f236d98e3f734fd61c35502b7137/assets/pid.jpg -------------------------------------------------------------------------------- /assets/search.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mentebinaria/maProc/dee8d4c17bc7f236d98e3f734fd61c35502b7137/assets/search.jpg -------------------------------------------------------------------------------- /assets/sstopTerminal.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mentebinaria/maProc/dee8d4c17bc7f236d98e3f734fd61c35502b7137/assets/sstopTerminal.jpg -------------------------------------------------------------------------------- /assets/stopp.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mentebinaria/maProc/dee8d4c17bc7f236d98e3f734fd61c35502b7137/assets/stopp.jpg -------------------------------------------------------------------------------- /assets/viewAddress.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mentebinaria/maProc/dee8d4c17bc7f236d98e3f734fd61c35502b7137/assets/viewAddress.jpg -------------------------------------------------------------------------------- /src/dirwindow.cpp: -------------------------------------------------------------------------------- 1 | #include "dirwindow.hpp" 2 | #include "include/data/win/structs.hpp" 3 | #include "gui/ui_dirwindow.h" 4 | 5 | #include 6 | #include 7 | 8 | DirWindow::DirWindow(QWidget *p_parent) : QDialog(p_parent), 9 | m_ui(new Ui::DirWindow), 10 | m_pid(0) 11 | { 12 | m_ui->setupUi(this); 13 | Conf_pidTable(); 14 | Set_pidTable(); 15 | } 16 | 17 | DirWindow::~DirWindow() 18 | { 19 | delete m_ui; 20 | } 21 | 22 | /** 23 | * @brief will configure the pid table 24 | */ 25 | void DirWindow::Conf_pidTable(void) 26 | { 27 | // m_ui->pidTable->horizontalHeader()->setSectionResizeMode(QHeaderView::Stretch); 28 | m_ui->pidTable->setEditTriggers(QAbstractItemView::NoEditTriggers); 29 | m_ui->pidTable->verticalHeader()->setVisible(false); 30 | m_ui->search->setPlaceholderText("Find"); 31 | } 32 | 33 | /** 34 | * @brief will add all pid to table 35 | */ 36 | void DirWindow::Set_pidTable() 37 | { 38 | m_ps.Reading_DirProcess(m_umap); 39 | 40 | for (auto &x : m_umap) 41 | { 42 | m_ui->pidTable->insertRow(m_ui->pidTable->rowCount()); 43 | int rowCount = m_ui->pidTable->rowCount() - 1; 44 | 45 | m_ui->pidTable->setItem(rowCount, Pid, new QTableWidgetItem(QString(QString::fromStdString(x.second.pid)))); 46 | m_ui->pidTable->setItem(rowCount, Name, new QTableWidgetItem(QString(QString::fromStdString(x.first)))); 47 | m_ui->pidTable->setItem(rowCount, User, new QTableWidgetItem(QString(QString::fromStdString(x.second.user)))); 48 | } 49 | 50 | m_ui->foundLabel->setText("Found " + QString::number(m_ui->pidTable->rowCount())); 51 | } 52 | 53 | /** 54 | * @brief 55 | * 56 | * @param index 57 | */ 58 | void DirWindow::on_pidTable_doubleClicked(const QModelIndex &p_index) 59 | { 60 | if (p_index.column() == 2) 61 | return; 62 | 63 | try 64 | { 65 | setPid(p_index.model()->data(p_index).toString()); 66 | } 67 | catch (std::exception &error) 68 | { 69 | QMessageBox::critical(nullptr, "Error", "Verify pid " + QString::fromStdString(std::to_string(m_pid)+" error unexpected")); 70 | } 71 | } 72 | 73 | /** 74 | * @brief get pid clicked in pid table 75 | * 76 | * @return pid_t pid 77 | */ 78 | pid_t DirWindow::getPid() 79 | { 80 | return m_pid; 81 | } 82 | 83 | /** 84 | * @brief set pid in table 85 | * 86 | * @param p_pid 87 | */ 88 | void DirWindow::setPid(QString p_pid) 89 | { 90 | try 91 | { 92 | m_pid = std::stoi(m_umap[p_pid.toStdString()].pid); 93 | } 94 | catch (std::exception &error) 95 | { 96 | m_pid = std::stoi(p_pid.toStdString()); 97 | } 98 | 99 | close(); 100 | } 101 | 102 | void DirWindow::on_search_textEdited(const QString &p_arg1) 103 | { 104 | for (int i = 0; i < m_ui->pidTable->rowCount(); i++) 105 | m_ui->pidTable->hideRow(i); 106 | 107 | QList search = m_ui->pidTable->findItems(p_arg1, Qt::MatchContains); 108 | 109 | foreach (auto &Ptr, search) 110 | { 111 | m_ui->pidTable->showRow(Ptr->row()); 112 | m_ui->foundLabel->setText("Found " + QString::number(search.size())); 113 | } 114 | 115 | if (p_arg1.size() == 0) 116 | m_ui->foundLabel->setText("Found " + QString::number(m_ui->pidTable->rowCount())); 117 | 118 | search.clear(); 119 | } -------------------------------------------------------------------------------- /src/dirwindow.hpp: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include 4 | #include 5 | 6 | #include "include/ps/ps.hpp" 7 | #include "mainwindow.hpp" 8 | 9 | namespace Ui 10 | { 11 | class DirWindow; 12 | } 13 | 14 | class DirWindow : public QDialog 15 | { 16 | Q_OBJECT 17 | 18 | private: 19 | std::unordered_map m_umap; 20 | Ui::DirWindow *m_ui; 21 | pid_t m_pid; 22 | Ps m_ps; 23 | 24 | void Conf_pidTable(); 25 | void setPid(QString); 26 | void Set_pidTable(); 27 | 28 | public: 29 | explicit DirWindow(QWidget * = nullptr); 30 | virtual ~DirWindow(); 31 | 32 | pid_t getPid(); 33 | 34 | private slots: 35 | void on_search_textEdited(const QString &); 36 | void on_pidTable_doubleClicked(const QModelIndex &); 37 | }; 38 | -------------------------------------------------------------------------------- /src/gui/about.ui: -------------------------------------------------------------------------------- 1 | 2 | 3 | m_about 4 | 5 | 6 | 7 | 0 8 | 0 9 | 720 10 | 316 11 | 12 | 13 | 14 | 15 | 720 16 | 316 17 | 18 | 19 | 20 | 21 | 720 22 | 350 23 | 24 | 25 | 26 | 27 | 600 28 | 100 29 | 30 | 31 | 32 | About 33 | 34 | 35 | 36 | 37 | 38 | 39 | 320 40 | 0 41 | 42 | 43 | 44 | 45 | 400 46 | 16777215 47 | 48 | 49 | 50 | true 51 | 52 | 53 | 54 | 55 | 0 56 | 0 57 | 353 58 | 296 59 | 60 | 61 | 62 | 63 | 64 | 65 | 66 | 200 67 | 200 68 | 69 | 70 | 71 | <html><head/><body><p><span style=" font-size:12pt; font-weight:600; font-style:italic; color:#54932a;">maProc v0.2.5</span></p></body></html> 72 | 73 | 74 | 75 | 76 | 77 | 78 | 79 | 0 80 | 120 81 | 82 | 83 | 84 | 85 | 370 86 | 100 87 | 88 | 89 | 90 | Report 91 | 92 | 93 | 94 | 95 | 96 | <html><head/><body><p><span style=" font-size:7pt; font-weight:600; color:#000000;">You may encounter any problem using the software, maProc,</span></p><p><span style=" font-size:7pt; font-weight:600; color:#000000;">just ask a question in question, it may be a feature,</span></p><p><span style=" font-size:7pt; font-weight:600; color:#000000;">which you want mapoc to implement, </span><a href="https://github.com/mentebinaria/maProc/issues"><span style=" text-decoration: underline; color:#0082fa;">report</span></a></p></body></html> 97 | 98 | 99 | 100 | 101 | 102 | 103 | 104 | 105 | 106 | 107 | 0 108 | 100 109 | 110 | 111 | 112 | 113 | 350 114 | 250 115 | 116 | 117 | 118 | Copyright © 119 | 120 | 121 | 122 | 123 | 124 | 125 | 100 126 | 0 127 | 128 | 129 | 130 | 131 | 350 132 | 350 133 | 134 | 135 | 136 | <html><head/><body><p align="center"><span style=" font-weight:600; color:#000000;">License : </span><a href="https://opensource.org/licenses/BSD-2-Clause"><span style=" text-decoration: underline; color:#0082fa;">BSD 2-clause </span></a></p><p align="center"><span style=" font-weight:600; color:#000000;">Copyright© :</span><a href="https://www.mentebinaria.com.br"><span style=" text-decoration: underline; color:#0082fa;">Mente Binária </span></a></p><p align="center"><span style=" font-weight:600; color:#000000;">Creators: </span><a href="https://github.com/VitorMob"><span style=" text-decoration: underline; color:#0082fa;">Mob</span></a><span style=" font-weight:600; color:#000000;">, </span><a href="https://github.com/AandersonL"><span style=" text-decoration: underline; color:#0082fa;">Buzzer</span></a><span style=" text-decoration: underline;"><br/></span></p><p align="center"><span style=" text-decoration: underline;"><br/></span></p></body></html> 137 | 138 | 139 | 140 | 141 | 142 | 143 | 144 | 145 | 146 | 147 | 148 | 149 | 150 | 151 | 270 152 | 0 153 | 154 | 155 | 156 | true 157 | 158 | 159 | 160 | 161 | 0 162 | 0 163 | 339 164 | 296 165 | 166 | 167 | 168 | 169 | 170 | 171 | 172 | 200 173 | 200 174 | 175 | 176 | 177 | 178 | 270 179 | 16777215 180 | 181 | 182 | 183 | Description 184 | 185 | 186 | 187 | 188 | 189 | 190 | 10 191 | 10 192 | 193 | 194 | 195 | <html><head/><body><p><span style=" font-weight:600; font-style:italic; color:#000000;">The name </span><span style=" font-weight:600; font-style:italic; color:#416f24;">maProc</span><span style=" font-weight:600; font-style:italic; color:#000000;"> informs, it will map</span></p><p><span style=" font-weight:600; font-style:italic; color:#000000;">processes in being able to check a </span></p><p><span style=" font-weight:600; font-style:italic; color:#000000;">process's stack/heap,being able </span></p><p><span style=" font-weight:600; font-style:italic; color:#000000;">to change the memory with write</span></p><p><span style=" font-weight:600; font-style:italic; color:#000000;">permission, you can manipulate</span></p><p><span style=" font-weight:600; font-style:italic; color:#000000;">the process by sending a </span></p><p><span style=" font-weight:600; font-style:italic; color:#000000;">SIGNAL and can stop or</span></p><p><span style=" font-weight:600; font-style:italic; color:#000000;"> pause it process.</span></p></body></html> 196 | 197 | 198 | 199 | 200 | 201 | 202 | 203 | 204 | 205 | 206 | 207 | 208 | 209 | 210 | 211 | -------------------------------------------------------------------------------- /src/gui/assets/about.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mentebinaria/maProc/dee8d4c17bc7f236d98e3f734fd61c35502b7137/src/gui/assets/about.png -------------------------------------------------------------------------------- /src/gui/assets/clean.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mentebinaria/maProc/dee8d4c17bc7f236d98e3f734fd61c35502b7137/src/gui/assets/clean.png -------------------------------------------------------------------------------- /src/gui/assets/close.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mentebinaria/maProc/dee8d4c17bc7f236d98e3f734fd61c35502b7137/src/gui/assets/close.png -------------------------------------------------------------------------------- /src/gui/assets/edit.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mentebinaria/maProc/dee8d4c17bc7f236d98e3f734fd61c35502b7137/src/gui/assets/edit.png -------------------------------------------------------------------------------- /src/gui/assets/help.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mentebinaria/maProc/dee8d4c17bc7f236d98e3f734fd61c35502b7137/src/gui/assets/help.png -------------------------------------------------------------------------------- /src/gui/assets/hex.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mentebinaria/maProc/dee8d4c17bc7f236d98e3f734fd61c35502b7137/src/gui/assets/hex.png -------------------------------------------------------------------------------- /src/gui/assets/kill.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mentebinaria/maProc/dee8d4c17bc7f236d98e3f734fd61c35502b7137/src/gui/assets/kill.png -------------------------------------------------------------------------------- /src/gui/assets/maProc.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mentebinaria/maProc/dee8d4c17bc7f236d98e3f734fd61c35502b7137/src/gui/assets/maProc.png -------------------------------------------------------------------------------- /src/gui/assets/new.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mentebinaria/maProc/dee8d4c17bc7f236d98e3f734fd61c35502b7137/src/gui/assets/new.png -------------------------------------------------------------------------------- /src/gui/assets/pid_proc.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mentebinaria/maProc/dee8d4c17bc7f236d98e3f734fd61c35502b7137/src/gui/assets/pid_proc.png -------------------------------------------------------------------------------- /src/gui/assets/play.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mentebinaria/maProc/dee8d4c17bc7f236d98e3f734fd61c35502b7137/src/gui/assets/play.png -------------------------------------------------------------------------------- /src/gui/assets/rpid.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mentebinaria/maProc/dee8d4c17bc7f236d98e3f734fd61c35502b7137/src/gui/assets/rpid.png -------------------------------------------------------------------------------- /src/gui/assets/save.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mentebinaria/maProc/dee8d4c17bc7f236d98e3f734fd61c35502b7137/src/gui/assets/save.png -------------------------------------------------------------------------------- /src/gui/assets/search.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mentebinaria/maProc/dee8d4c17bc7f236d98e3f734fd61c35502b7137/src/gui/assets/search.png -------------------------------------------------------------------------------- /src/gui/assets/show.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mentebinaria/maProc/dee8d4c17bc7f236d98e3f734fd61c35502b7137/src/gui/assets/show.png -------------------------------------------------------------------------------- /src/gui/assets/stop.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mentebinaria/maProc/dee8d4c17bc7f236d98e3f734fd61c35502b7137/src/gui/assets/stop.png -------------------------------------------------------------------------------- /src/gui/dirwindow.ui: -------------------------------------------------------------------------------- 1 | 2 | 3 | DirWindow 4 | 5 | 6 | 7 | 0 8 | 0 9 | 516 10 | 516 11 | 12 | 13 | 14 | 15 | 516 16 | 516 17 | 18 | 19 | 20 | 21 | 516 22 | 516 23 | 24 | 25 | 26 | List Process 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 500 36 | 400 37 | 38 | 39 | 40 | 41 | 1000 42 | 1000 43 | 44 | 45 | 46 | ArrowCursor 47 | 48 | 49 | Qt::ElideMiddle 50 | 51 | 52 | Qt::DotLine 53 | 54 | 55 | true 56 | 57 | 58 | true 59 | 60 | 61 | false 62 | 63 | 64 | 65 | Pid 66 | 67 | 68 | 69 | 70 | Name 71 | 72 | 73 | 74 | 75 | 76 | 77 | 78 | 79 | 80 | 81 | User 82 | 83 | 84 | 85 | 86 | 87 | 88 | 89 | 90 | 91 | 92 | 120 93 | 30 94 | 95 | 96 | 97 | 98 | 120 99 | 30 100 | 101 | 102 | 103 | 104 | 105 | 106 | 107 | 108 | 109 | Qt::VisualMoveStyle 110 | 111 | 112 | false 113 | 114 | 115 | 116 | 117 | 118 | 119 | 120 | 100 121 | 16777215 122 | 123 | 124 | 125 | Found: 0 126 | 127 | 128 | 129 | 130 | 131 | 132 | 133 | 134 | 135 | 136 | 137 | 138 | 139 | -------------------------------------------------------------------------------- /src/gui/style/dark.css: -------------------------------------------------------------------------------- 1 | /* 2 | * TODO: Search buttons color (Replace, Replace and continue search) 3 | */ 4 | 5 | /* 6 | * Drop background color of most widgets 7 | */ 8 | 9 | QWidget, QStackedWidget, 10 | QScrollArea, QAbstractScrollArea { 11 | background-color: transparent; 12 | } 13 | 14 | QApplication, 15 | QMainWindow, QFrame, QDockWidget, QDialog, QFileDialog, QMessageBox, 16 | QRadioButton, 17 | QGroupBox::title, /* Need to set background becase must clear border behind label */ 18 | QMenuBar, QMenu, QMenu::item, 19 | QComboBox QAbstractItemView, 20 | QTreeView, QListWidget, QListView, QTableWidget, QTableView, 21 | QTextEdit, QTextBrowser { 22 | background-color: #3c3f41; /*#004100;*/ 23 | color: #bbbbbb; 24 | } 25 | 26 | /* 27 | * This is default values 28 | * Edit first if you want change appearance 29 | */ 30 | 31 | QLabel, QTabBar::tab, QMenuBar::item, 32 | QCheckBox, QGroupBox { 33 | background-color: transparent; 34 | color: #bbbbbb; 35 | selection-color: #bbbbbb; 36 | } 37 | 38 | /* 39 | * GroupBox and CheckBox 40 | * 41 | * TODO: ::indicator:indeterminate icons 42 | */ 43 | 44 | QGroupBox { 45 | border-top: 1px solid #2d2d2d; 46 | margin-top: 0.5em; 47 | } 48 | QGroupBox::title { 49 | subcontrol-origin: margin; 50 | subcontrol-position: top left; 51 | padding: 0 3px; 52 | } 53 | QCheckBox::indicator, 54 | QGroupBox::indicator { 55 | width: 13px; 56 | height: 13px; 57 | } 58 | QCheckBox::indicator:unchecked, 59 | QGroupBox::indicator:unchecked { 60 | image: url(:/qmldesigner/images/checkbox_unchecked.png); 61 | } 62 | QCheckBox::indicator:unchecked:hover, 63 | QGroupBox::indicator:unchecked:hover { 64 | image: url(:/qmldesigner/images/checkbox_unchecked_hover.png); 65 | } 66 | QCheckBox::indicator:unchecked:pressed, 67 | QGroupBox::indicator:unchecked:pressed { 68 | image: url(:/qmldesigner/images/checkbox_unchecked_pressed.png); 69 | } 70 | QCheckBox::indicator:checked, 71 | QGroupBox::indicator:checked { 72 | image: url(:/qmldesigner/images/checkbox_checked.png); 73 | } 74 | QCheckBox::indicator:checked:hover, 75 | QGroupBox::indicator:checked:hover { 76 | image: url(:/qmldesigner/images/checkbox_checked_hover.png); 77 | } 78 | QCheckBox::indicator:checked:pressed, 79 | QGroupBox::indicator:checked:pressed { 80 | image: url(:/qmldesigner/images/checkbox_checked_pressed.png); 81 | } 82 | QCheckBox::indicator:indeterminate:hover, 83 | QGroupBox::indicator:indeterminate:hover { 84 | background-color: #2222bb; 85 | image: url(:/qmldesigner/images/checkbox_indeterminate_hover.png); /* TODO: There is no shuch image */ 86 | } 87 | QCheckBox::indicator:indeterminate:pressed, 88 | QGroupBox::indicator:indeterminate:pressed { 89 | background-color: #22bb22; 90 | image: url(:/qmldesigner/images/checkbox_indeterminate_pressed.png); /* TODO: There is no shuch image */ 91 | } 92 | 93 | 94 | QLineEdit, QAbstractSpinBox, QComboBox, QPushButton { 95 | background-color: #45494a; 96 | /*background-color: rgba(255, 255, 255, 0.05);*/ 97 | 98 | background-origin: border; 99 | border: 1px solid #646464; 100 | color: #bbbbbb; 101 | min-width: 3em; 102 | padding: 0px 1px 2px 3px; 103 | selection-background-color: #4b6eaf; 104 | }/*:focus 105 | { 106 | outline: 3px ridge #4e78a2; 107 | border-radius: 2px; 108 | } 109 | :edit-focus 110 | { 111 | border: 1px solid red; 112 | }*/ 113 | :read-only { 114 | background-color: transparent; 115 | border: 1px solid #535353; 116 | color: #999999; 117 | } 118 | :no-frame { 119 | border-width: 0; 120 | } 121 | 122 | /* 123 | * Any SpinBox (e.g. DoubleSpinbox) 124 | * 125 | * TODO: Icons not fit into the overall style 126 | */ 127 | QAbstractSpinBox::up-button { 128 | image: url(:/qmldesigner/images/spinup.png); 129 | } 130 | QAbstractSpinBox::up-button:hover { 131 | image: url(:/qmldesigner/images/spinup_hover.png); 132 | } 133 | QAbstractSpinBox::up-button:off { 134 | image: url(:/qmldesigner/images/spinup_off.png); 135 | } 136 | QAbstractSpinBox::up-button:pressed { 137 | image: url(:/qmldesigner/images/spinup_pressed.png); 138 | } 139 | QAbstractSpinBox::down-button { 140 | image: url(:/qmldesigner/images/spindown.png); 141 | } 142 | QAbstractSpinBox::down-button:hover { 143 | image: url(:/qmldesigner/images/spindown_hover.png); 144 | } 145 | QAbstractSpinBox::down-button:off { 146 | image: url(:/qmldesigner/images/spindown_off.png); 147 | } 148 | QAbstractSpinBox::down-button:pressed { 149 | image: url(:/qmldesigner/images/spindown_pressed.png); 150 | } 151 | 152 | 153 | /* 154 | * PushButton and Utils::QtColorButton 155 | * 156 | * TODO: Customize :pressed 157 | * FIXME: Outline is positioned around content, but should around padding 158 | */ 159 | 160 | QPushButton { 161 | min-height: 1.33em; 162 | min-width: 5.25em; 163 | outline: 0; 164 | } 165 | Utils--QtColorButton, 166 | QPushButton { 167 | background-color: qlineargradient(x1: 0, y1: 0, x2: 0, y2: 1, stop: 0 #515658, stop: 1.0 #44494b); 168 | border: 1px solid #5f6161; 169 | border-radius: 2px; 170 | } 171 | Utils--QtColorButton:pressed, 172 | QPushButton:pressed { 173 | border-style: inset; 174 | } 175 | QPushButton:default { 176 | background-color: qlineargradient(x1: 0, y1: 0, x2: 0, y2: 1, stop: 0 #344a64, stop: 1.0 #263549); 177 | } 178 | Utils--QtColorButton:disabled, 179 | QPushButton:disabled { 180 | background-color: transparent; 181 | color: #999999; 182 | } 183 | Utils--QtColorButton:open, 184 | QPushButton:open { 185 | background-color: #4b6eaf; 186 | } 187 | QPushButton::menu-indicator { 188 | subcontrol-origin: content; 189 | subcontrol-position: bottom right; 190 | } 191 | 192 | /* 193 | * ComboBox 194 | */ 195 | QComboBox { 196 | border-radius: 2px; 197 | min-width: 3em; 198 | padding: 0px 1px 2px 3px; 199 | } 200 | QComboBox:!editable { 201 | /*background-color: rgba(63, 113, 73, 0.2);*/ 202 | /*background-color: #45494a;*/ 203 | background-color: rgba(255, 255, 255, 0.05); 204 | } 205 | /* 206 | QComboBox:!editable:on 207 | QComboBox::drop-down:editable:on 208 | QComboBox::drop-down:editable 209 | */ 210 | QComboBox:on { 211 | padding-top: 3px; 212 | padding-left: 4px; 213 | } 214 | QComboBox::down-arrow { 215 | image: url(:/qmldesigner/images/triangle_vert.png); 216 | } 217 | QComboBox::down-arrow:on { 218 | top: 1px; 219 | left: 1px; 220 | } 221 | QComboBox::drop-down { 222 | border-left: 1px solid #646464; 223 | } 224 | QComboBox QAbstractItemView { 225 | border: 1px solid red;/*black;*/ 226 | /*selection-background-color: #d2d2d2; 227 | selection-color: #404040; 228 | show-decoration-selected: 1; /* make the selection span the entire width of the view */ 229 | } 230 | 231 | 232 | /* 233 | * RadioButton 234 | * 235 | * TODO: Checked circle is hard to spot 236 | */ 237 | QRadioButton::indicator { 238 | width: 13px; 239 | height: 13px; 240 | } 241 | QRadioButton::indicator:unchecked { 242 | image: url(:/qmldesigner/images/radiobutton_unchecked.png); 243 | } 244 | QRadioButton::indicator:unchecked:hover { 245 | image: url(:/qmldesigner/images/radiobutton_unchecked_hover.png); 246 | } 247 | QRadioButton::indicator:unchecked:pressed { 248 | image: url(:/qmldesigner/images/radiobutton_unchecked_pressed.png); 249 | } 250 | QRadioButton::indicator:checked { 251 | image: url(:/qmldesigner/images/radiobutton_checked.png); 252 | } 253 | QRadioButton::indicator:checked:hover { 254 | image: url(:/qmldesigner/images/radiobutton_checked_hover.png); 255 | } 256 | QRadioButton::indicator:checked:pressed { 257 | image: url(:/qmldesigner/images/radiobutton_checked_pressed.png); 258 | } 259 | 260 | 261 | /* 262 | * TabWidget and TabBar 263 | * 264 | * FIXME: Designer bottom tabbar problem 265 | * TODO: Customize QTabBar::tab:hover 266 | */ 267 | QTabWidget::tab-bar { 268 | /*position: relative; 269 | bottom: -1px;*/ 270 | } 271 | QTabWidget::pane { 272 | background-color: transparent; 273 | border: 1px solid #323232; 274 | } 275 | QTabWidget::pane:top { 276 | top: -1px; 277 | } 278 | QTabWidget::pane:right { 279 | right: -1px; 280 | } 281 | QTabWidget::pane:bottom { 282 | bottom: -1px; 283 | } 284 | QTabWidget::pane:left { 285 | left: -1px; 286 | } 287 | QTabBar::tab { 288 | border: 1px solid #292b2d; 289 | min-width: 8ex; 290 | padding: 4px; 291 | } 292 | /*QTabBar::tab:hover { 293 | background-color: #4b6eaf; 294 | }*/ 295 | QTabBar::tab:top { 296 | border-top-left-radius: 4px; 297 | border-top-right-radius: 4px; 298 | } 299 | QTabBar::tab:right { 300 | border-top-right-radius: 4px; 301 | border-bottom-right-radius: 4px; 302 | } 303 | QTabBar::tab:bottom { 304 | border-bottom-left-radius: 4px; 305 | border-bottom-right-radius: 4px; 306 | } 307 | QTabBar::tab:left { 308 | border-top-left-radius: 4px; 309 | border-bottom-left-radius: 4px; 310 | } 311 | QTabBar::tab:selected { 312 | background-color: #41516d; 313 | } 314 | QTabBar::tab:top:selected { 315 | border-bottom-color: #41516d; 316 | } 317 | QTabBar::tab:right:selected { 318 | border-left-color: #41516d; 319 | } 320 | QTabBar::tab:bottom:selected { 321 | border-top-color: #41516d; 322 | } 323 | QTabBar::tab:left:selected { 324 | border-right-color: #41516d; 325 | } 326 | QTabBar::tab:top:!selected { 327 | margin-top: 2px; 328 | } 329 | QTabBar::tab:right:!selected { 330 | margin-right: 2px; 331 | } 332 | QTabBar::tab:bottom:!selected { 333 | margin-bottom: 2px; 334 | } 335 | QTabBar::tab:left:!selected { 336 | margin-left: 2px; 337 | } 338 | 339 | /* 340 | * Table 341 | * 342 | * FIXME: Problem with arrows positioning workarounded in bad way 343 | * FIXME: Unknown problem Options > FakeVim > User Command Mapping 344 | * QT-BUG: Wrong behaviour property min-height of QHeaderView::section 345 | */ 346 | 347 | QTableWidget, 348 | QTableView { 349 | /* This rule have more priority than previous?! 350 | * And overrides with empty if not declared! */ 351 | /*background: red; /*transparent;*/ 352 | /*color: #bbbbbb;*/ 353 | 354 | border: 1px solid #323232; 355 | alternate-background-color: #414547; /* Dont work without setAlternatingRowColors(true) */ 356 | } 357 | QTableView QTableCornerButton::section { 358 | background-color: green; /*FIXME*/ 359 | border: 2px outset blue; /*FIXME*/ 360 | } 361 | QHeaderView::section { 362 | background-color: qlineargradient(x1: 0, y1: 0, x2: 0, y2: 1, stop:0 #54585b, stop:1 #393c3e); 363 | color: #bbbbbb; 364 | padding: 1px 2px 1px 4px; 365 | 366 | border: 1px solid #323232; 367 | border-top-width: 0; 368 | border-left-color: #5e6163; 369 | border-right-color: #2a2c2d; 370 | 371 | /*min-height: 15px;*/ 372 | } 373 | QHeaderView::section:hover { 374 | background-color: qlineargradient(x1: 0, y1: 0, x2: 0, y2: 1, stop:0 #64686b, stop:1 #494c4e); 375 | border-bottom-color: #424242; 376 | } 377 | QHeaderView::section:first { 378 | border-left-width: 0; 379 | } 380 | QHeaderView::section:last { 381 | border-right-width: 0; 382 | } 383 | QHeaderView::section:checked { 384 | background-color: red; /*FIXME*/ 385 | } 386 | QHeaderView::down-arrow { 387 | image: url(:/qmldesigner/images/down_arrow.png); 388 | right: 7px; 389 | } 390 | QHeaderView::up-arrow { 391 | image: url(:/qmldesigner/images/up_arrow.png); 392 | /* image-position: right; Don't work */ 393 | /*right: 7px; */ 394 | height: 7px; 395 | width: 7px; 396 | } 397 | 398 | /* 399 | * Menu and MenuBar 400 | * 401 | * TODO: Customize toggleable items 402 | */ 403 | QMenuBar { 404 | /*background-color: #3c3f41; /* transparent don't work */ 405 | border-bottom: 2px solid qlineargradient(x1: 0, y1: 0, x2: 0, y2: 1, stop:0 #282828, stop:1 #555555); 406 | } 407 | QMenuBar::item:pressed { 408 | background-color: #4b6eaf; 409 | } 410 | QMenuBar::item:selected:!pressed { 411 | background-color: #585b5d; 412 | } 413 | QMenu { 414 | border: 1px solid #2d2d2d; 415 | } 416 | /*QMenu::item { 417 | margin-left: 3px; 418 | }*/ 419 | QMenu::item:disabled { 420 | color: #999999; 421 | } 422 | QMenu::item:selected { 423 | background-color: #4b6eaf; 424 | } 425 | QMenu::icon { 426 | border: 0px solid transparent; 427 | background-color: transparent; 428 | } 429 | QMenu::icon:checked { 430 | background-color: blue; 431 | border: 1px inset red; 432 | position: absolute; 433 | top: 1px; 434 | right: 1px; 435 | bottom: 1px; 436 | left: 1px; 437 | } 438 | QMenu::separator { 439 | height: 2px; 440 | background-color: qlineargradient(x1: 0, y1: 0, x2: 0, y2: 1, stop:0 #282a2b, stop:1 #45484b); 441 | margin: 0 1px; 442 | } 443 | /*QMenu::indicator { 444 | width: 13px; 445 | height: 13px; 446 | background-color: blue; 447 | }*/ 448 | 449 | 450 | /* 451 | * Scroll bar modifications 452 | */ 453 | QScrollBar { 454 | background-color: transparent; 455 | margin: 0; 456 | height: 12px; /* for horizontal */ 457 | width: 12px; /* for vertical */ 458 | } 459 | QScrollBar::handle { 460 | border: 1px solid #555555; 461 | border-radius: 4px; 462 | margin: 1px; 463 | } 464 | QScrollBar::handle:vertical { 465 | background-color: qlineargradient(x1: 0, y1: 0, x2: 1, y2: 0, stop:0 #5c5c5c, stop:1 #515151); 466 | min-height: 20px; 467 | min-width: 8px; 468 | } 469 | QScrollBar::handle:vertical:hover { 470 | background-color: qlineargradient(x1: 0, y1: 0, x2: 1, y2: 0, stop:0 #666666, stop:1 #5b5b5b); 471 | } 472 | QScrollBar::handle:horizontal { 473 | background-color: qlineargradient(x1: 0, y1: 0, x2: 0, y2: 1, stop:0 #5c5c5c, stop:1 #515151); 474 | min-height: 8px; 475 | min-width: 20px; 476 | } 477 | QScrollBar::handle:horizontal:hover { 478 | background-color: qlineargradient(x1: 0, y1: 0, x2: 0, y2: 1, stop:0 #666666, stop:1 #5b5b5b); 479 | } 480 | QScrollBar::add-page:vertical, QScrollBar::sub-page:vertical, 481 | QScrollBar::add-page:horizontal, QScrollBar::sub-page:horizontal { 482 | background-color: transparent; 483 | } 484 | /*QScrollBar::sub-page:vertical { 485 | max-height: 8px; 486 | margin-top: auto; 487 | margin-bottom: 0; 488 | background-color: purple; 489 | border-top-left-radius: 4px; 490 | border-top-right-radius: 4px; 491 | } 492 | QScrollBar::add-page:vertical { 493 | max-height: 8px; 494 | margin-top: 0; 495 | margin-bottom: auto; 496 | background-color: darkblue; 497 | border-bottom-left-radius: 4px; 498 | border-bottom-right-radius: 4px; 499 | }*/ 500 | QScrollBar::add-line:vertical, QScrollBar::sub-line:vertical, 501 | QScrollBar::add-line:horizontal, QScrollBar::sub-line:horizontal { 502 | height: 0; 503 | width: 0; 504 | } 505 | 506 | /* 507 | * Status bar 508 | */ 509 | /* 510 | QStatusBar { 511 | background-color: brown; 512 | border: 1px solid brown; 513 | } 514 | QStatusBar::item { 515 | background-color: red; 516 | border: 1px solid red; 517 | border-radius: 3px; 518 | } 519 | QStatusBar QLabel { 520 | background-color: green; 521 | border: 3px solid green; 522 | } 523 | */ 524 | 525 | 526 | /* 527 | * QAbstractItemView modifications 528 | * 529 | * TODO: ::indicator 530 | * TODO: Disable item icon selection mask 531 | * FIXME: Transparent selection background on some elements Options > BlackBerry > API Levels and Runtimes 532 | * QT-BUG: Strange behaviour of selection-* properties (always :!focus) 533 | */ 534 | QAbstractItemView { 535 | border: 1px solid #323232; 536 | selection-color: #bbbbbb; 537 | selection-background-color: #4b6eaf; 538 | alternate-background-color: #414547; /* Works only if setAlternatingRowColors(true) */ 539 | show-decoration-selected: 1; 540 | outline: 0; 541 | } 542 | /* 543 | QAbstractItemView:!focus { 544 | selection-background-color: #0d293e; 545 | } 546 | QTreeView::branch, 547 | QAbstractItemView::item { 548 | border-width: 0; 549 | } 550 | */ 551 | QAbstractItemView::item:alternate { 552 | background-color: #414547; 553 | } 554 | QListWidgetItem, 555 | QTreeWidgetItem { 556 | background-color: red; 557 | color: yellow; 558 | border: 1px solid purple; 559 | } 560 | QAbstractItemView::text { 561 | color: #bbbbbb; 562 | } 563 | QTreeView::branch:hover, 564 | QAbstractItemView::item:hover { 565 | background-color: rgba(255, 255, 255, 0.05); 566 | } 567 | QTreeView::branch:selected:active, 568 | QAbstractItemView::item:selected { 569 | background-color: #4b6eaf; 570 | } 571 | /* No way due to another bug :( 572 | QTreeView::branch:selected:active, 573 | QAbstractItemView::item:selected:active { 574 | background-color: #4b6eaf; 575 | } 576 | QTreeView::branch:selected:!active, 577 | QAbstractItemView::item:selected:!active { 578 | background-color: #0d293e; 579 | } 580 | */ 581 | QTreeView::branch:has-siblings:adjoins-item, 582 | QTreeView::branch:has-siblings:!adjoins-item, 583 | QTreeView::branch:!has-children:!has-siblings:adjoins-item { 584 | border-image: none; 585 | image: none; 586 | } 587 | QTreeView::branch:has-children:!has-siblings:closed, 588 | QTreeView::branch:closed:has-children:has-siblings { 589 | border-image: none; 590 | image: url(:/qmldesigner/images/triangle_horz.png); 591 | } 592 | QTreeView::branch:open:has-children:!has-siblings, 593 | QTreeView::branch:open:has-children:has-siblings { 594 | border-image: none; 595 | image: url(:/qmldesigner/images/triangle_vert.png); 596 | } 597 | 598 | /* 599 | * Tool bar 600 | */ 601 | 602 | QToolBar { 603 | border-width: 0; /* Cancels gradiend */ 604 | } 605 | 606 | /* 607 | * Resizing widget (bottom right in Qt Creator, inside status bar) 608 | */ 609 | 610 | QSizeGrip { 611 | image: url(:/qmldesigner/images/sizegrip.png); 612 | width: 16px; 613 | height: 16px; 614 | } 615 | 616 | /* 617 | * ToolTip 618 | */ 619 | 620 | QToolTip, QTipLabel { 621 | border: 1px solid #9a9a66; 622 | border-radius: 3px; 623 | background: #5c5c42; 624 | color: #bbbbbb; 625 | margin: 0; 626 | padding: 0; 627 | } 628 | 629 | /* 630 | * Wizard dialog 631 | * 632 | * TODO: Buttons bar background 633 | */ 634 | 635 | QWizard > QWidget { 636 | background-color: #3c3f41; 637 | } 638 | 639 | /* QT-BUG: Because QFrame { border-color: #323232; } has no effect */ 640 | Core--Internal--NewDialog > QFrame#frame { 641 | border: 1px solid #323232; 642 | } 643 | 644 | /* vvvvvvvvvvvvvvvvvvvvvvvvvv WORKAROUND vvvvvvvvvvvvvvvvvvvvvvvvvv */ 645 | /* Related to: 646 | * 1) https://bugreports.qt-project.org/browse/QTCREATORBUG-12078 647 | * 2) https://codereview.qt-project.org/#/c/74538/ 648 | * Because of bugs in QtGui, apllying stylesheet to QPlainTextEdit causes it 649 | * to lose font settings and palette on setParent event. So switching between 650 | * modes (Editor and Debug) or split Editor resets font and color of edit 651 | * and extra edit areas 652 | * To workaround this problems set you own peferred colors and font below 653 | */ 654 | QPlainTextEdit { 655 | background-color: #2b2b2b; 656 | selection-background-color: #214283; 657 | color: #bbbbbb; 658 | selection-color: #bbbbbb; /* No better workaround for this */ 659 | font: 10pt Courier, Inconsolata, Monospace; 660 | } 661 | /*TextEditor--Internal--TextEditExtraArea*/ 662 | TextEditor--TextEditorWidget > QWidget { 663 | background-color: #313335; 664 | selection-background-color: #4b6eaf; 665 | color: #bbbbbb; /* QT-BUG: Sadly this has no effect */ 666 | } 667 | /* ^^^^^^^^^^^^^^^^^^^^^^^^^^ WORKAROUND ^^^^^^^^^^^^^^^^^^^^^^^^^^ */ 668 | -------------------------------------------------------------------------------- /src/gui/style/light.css: -------------------------------------------------------------------------------- 1 | /** 2 | * @file: list.h 3 | * @details: qt style sheet css example 4 | * @author: chenwen(chenwen1126@tom.com) 5 | * @datetime: 2017-7-25 6 | * @history: V1.0 first edition 7 | */ 8 | /*/////////////////////////////////////////////////QDialog///////////////////////////////////////////*/ 9 | QWidget, QFrame,QDialog 10 | { 11 | background:#f2f2f2; 12 | } 13 | 14 | QMainWindow 15 | { 16 | background:#f2f2f2; 17 | } 18 | 19 | QWebView 20 | { 21 | background:#fefefe; 22 | } 23 | 24 | /*/////////////////////////////////////////////////QStatusBar///////////////////////////////////////////*/ 25 | QStatusBar 26 | { 27 | border-top:1px solid #aaaaaa; 28 | min-height:20px; 29 | background: qlineargradient(x1:0, y1:0, x2:0, y2:1, stop:0.2 #f4f4f4, stop:1 #e4e4e4);/*渐变背景色*/ 30 | } 31 | 32 | /*/////////////////////////////////////////////////工具栏及窗口边框///////////////////////////////////////////*/ 33 | /*窗口边框,可*/ 34 | QFrame#window 35 | { 36 | padding:0px; 37 | border-width:2px;/*边框宽度*/ 38 | border-style:solid;/*边框类型*/ 39 | /*用渐变色可以营造光晕边框效果*/ 40 | border-color:qlineargradient(x1:0, y1:1, x2:0, y2:0, stop:0 #999999, stop:1 #ffffff)/*上边框渐变色*/ 41 | qlineargradient(x1:0, y1:0, x2:1, y2:0, stop:0 #999999, stop:1 #ffffff)/*右边框渐变色*/ 42 | qlineargradient(x1:0, y1:0, x2:0, y2:1, stop:0 #999999, stop:1 #ffffff)/*下边框渐变色*/ 43 | qlineargradient(x1:1, y1:0, x2:0, y2:0, stop:0 #999999, stop:1 #ffffff);/*左边框渐变色*/ 44 | } 45 | 46 | QFrame#dialog,QFrame#messagebox 47 | { 48 | padding:12px;/*设置透明阴影留出的padding空间,通过源码绘制透明阴影 注意在代码中设置QSSDIALOG_SHADOW_WIDTH为12*/ 49 | border:0px solid #ff0000;/*指定边框为0,实际边框时绘制阴影时直接画de直线,边框颜色也是在代码中指定的*/ 50 | } 51 | 52 | /*标题栏*/ 53 | QWidget#titlebar 54 | { 55 | min-height:25px;/*用min-height设置标题栏高度*/ 56 | background: qlineargradient(x1:0, y1:0, x2:0, y2:1, stop:0.2 #e4e4e4, stop:1 #d4d4d4);/*渐变背景色*/ 57 | border-bottom:1px solid #aaaaaa; 58 | } 59 | 60 | QWidget:active#titlebar 61 | { 62 | min-height:25px;/*用min-height设置标题栏高度*/ 63 | 64 | background: qlineargradient(x1:0, y1:0, x2:0, y2:1, stop:0.2 #f4f4f4, stop:1 #e4e4e4);/*渐变背景色*/ 65 | border-bottom:1px solid #aaaaaa; 66 | } 67 | 68 | /*标题栏图标*/ 69 | QPushButton#titlebaricon 70 | { 71 | min-width:24px;/*覆盖QPushButton中设置*/ 72 | min-height:24px;/*覆盖QPushButton中设置*/ 73 | width:24px;/*宽度*/ 74 | height:24px; 75 | padding:0px; 76 | padding-left:2px; 77 | padding-right:-2px; 78 | background:transparent;/*无背景无边框*/ 79 | border:none; 80 | } 81 | 82 | /*标题栏标题*/ 83 | QLabel#titlebartitle 84 | { 85 | padding-left:2px; 86 | font-weight:bold; 87 | font-size:10pt; 88 | color:#222222; 89 | background:transparent; 90 | } 91 | 92 | /*标题栏关闭按钮*/ 93 | QPushButton#titlebarclosebtn 94 | { 95 | padding:0px; 96 | padding-right:3px; 97 | min-width:39px; 98 | min-height:19px; 99 | width:39px; 100 | height:19px; 101 | outline:none; 102 | border: none; 103 | background:transparent;/*无背景无边框*/ 104 | image:url(:/qss/icon/btn_close_highlight.png);/*btn_close_normal*/ 105 | } 106 | 107 | QPushButton#titlebarclosebtn:hover 108 | { 109 | min-width:39px; 110 | min-height:19px; 111 | width:39px; 112 | height:19px; 113 | image:url(:/qss/icon/btn_close_highlight.png); 114 | } 115 | 116 | QPushButton#titlebarclosebtn:pressed 117 | { 118 | min-width:39px; 119 | min-height:19px; 120 | width:39px; 121 | height:19px; 122 | image:url(:/qss/icon/btn_close_down.png); 123 | } 124 | 125 | /*标题栏最小化按钮*/ 126 | QPushButton#titlebarminbtn 127 | { 128 | padding:0px; 129 | min-width:28px; 130 | min-height:19px; 131 | width:28px; 132 | height:19px; 133 | outline:none; 134 | border: none; 135 | background:transparent; 136 | image:url(:/qss/icon/btn_mini_normal.png); 137 | } 138 | 139 | QPushButton#titlebarminbtn:hover 140 | { 141 | min-width:28px; 142 | min-height:19px; 143 | width:28px; 144 | height:19px; 145 | image:url(:/qss/icon/btn_mini_highlight.png); 146 | } 147 | 148 | QPushButton#titlebarminbtn:pressed 149 | { 150 | min-width:28px; 151 | min-height:19px; 152 | width:28px; 153 | height:19px; 154 | image:url(:/qss/icon/btn_mini_down.png); 155 | } 156 | 157 | /*标题栏最大化按钮*/ 158 | QPushButton#titlebarmaxbtn 159 | { 160 | padding:0px; 161 | padding-bottom:3px;/*因为图表资源尺寸不对,做的微调*/ 162 | border: none; 163 | min-width:25px; 164 | min-height:18px; 165 | width:25px; 166 | height:18px; 167 | outline:none; 168 | background:transparent; 169 | image:url(:/qss/icon/btn_max_normal.png); 170 | } 171 | 172 | QPushButton#titlebarmaxbtn:hover 173 | { 174 | min-width:28px; 175 | min-height:19px; 176 | width:28px; 177 | height:19px; 178 | image:url(:/qss/icon/btn_max_highlight.png); 179 | } 180 | 181 | QPushButton#titlebarmaxbtn:pressed 182 | { 183 | min-width:28px; 184 | min-height:19px; 185 | width:28px; 186 | height:19px; 187 | image:url(:/qss/icon/btn_max_down.png); 188 | } 189 | 190 | /*标题栏还原按钮*/ 191 | QPushButton#titlebarrestorebtn 192 | { 193 | padding:0px; 194 | padding-bottom:3px;/*因为图表资源尺寸不对,做的微调*/ 195 | border: none; 196 | min-width:25px; 197 | min-height:18px; 198 | width:25px; 199 | height:18px; 200 | outline:none; 201 | background:transparent; 202 | image:url(:/qss/icon/btn_restore_normal.png); 203 | } 204 | 205 | QPushButton#titlebarrestorebtn:hover 206 | { 207 | min-width:28px; 208 | min-height:20px; 209 | width:28px; 210 | height:20px; 211 | image:url(:/qss/icon/btn_restore_highlight.png); 212 | } 213 | 214 | QPushButton#titlebarrestorebtn:pressed 215 | { 216 | min-width:28px; 217 | min-height:20px; 218 | width:28px; 219 | height:20px; 220 | image:url(:/qss/icon/btn_restore_down.png); 221 | } 222 | 223 | /*/////////////////////////////////////////////////QPushButton///////////////////////////////////////////*/ 224 | /*为QPushButton设置通用属性*/ 225 | QPushButton 226 | { 227 | padding:0px 4px;/*上下padding为0px 左右未6px {1,4}为上右下左*/ 228 | min-width:80; 229 | min-height:24; 230 | border: 1px solid #aaaaaa;/*边框*/ 231 | background: qlineargradient(x1:0, y1:0, x2:0, y2:1, stop:0 #ffffff, stop:0.8 #eeeeee);/*渐变背景色*/ 232 | outline:none;/*表示foucs状态时取消虚线框*/ 233 | } 234 | 235 | QPushButton::disabled 236 | { 237 | background: qlineargradient(x1:0, y1:0, x2:0, y2:1, stop:0 #ffffff, stop:0.6 #eeeeee);/*渐变背景色*/ 238 | border: 1px solid #dddddd;/*边框*/ 239 | } 240 | 241 | /*为hover状态QPushButton设置属性,注意hover伪状态设置一定要在pressed伪状态之前!!!!!!!!!!*/ 242 | QPushButton:hover 243 | { 244 | background: qlineargradient(x1:0, y1:0, x2:0, y2:1, stop:0 #eeeeee, stop:0.8 #ffffff);/*渐变背景色*/ 245 | } 246 | 247 | /*为pressed状态QPushButton设置属性*/ 248 | QPushButton:pressed 249 | { 250 | background: qlineargradient(x1:0, y1:0, x2:0, y2:1, stop:0 #ffffff, stop:0.8 #dddddd);/*渐变背景色*/ 251 | } 252 | 253 | /*按钮为默认按钮时(不管焦点直接接收键盘回车输入的按钮),一般对话框ok按钮为默认按钮*/ 254 | .QPushButton:default 255 | { 256 | border-width:2px;/*边框宽度*/ 257 | border-style:solid;/*边框类型*/ 258 | /*用渐变色可以营造光晕边框效果*/ 259 | border-color:qlineargradient(x1:0, y1:1, x2:0, y2:0, stop:0 #64bff0, stop:1 #bae3f7)/*上边框渐变色*/ 260 | qlineargradient(x1:0, y1:0, x2:1, y2:0, stop:0 #64bff0, stop:1 #bae3f7)/*右边框渐变色*/ 261 | qlineargradient(x1:0, y1:0, x2:0, y2:1, stop:0 #64bff0, stop:1 #bae3f7)/*下边框渐变色*/ 262 | qlineargradient(x1:1, y1:0, x2:0, y2:0, stop:0 #64bff0, stop:1 #bae3f7);/*左边框渐变色*/ 263 | } 264 | 265 | /*为focus状态QPushButton设置属性,QPushButtond的子类,如QCommandLinkButton不设置该属性*/ 266 | .QPushButton:focus 267 | { 268 | border-width:2px;/*边框宽度*/ 269 | border-style:solid;/*边框类型*/ 270 | 271 | /*用渐变色可以营造光晕边框效果*/ 272 | border-color:qlineargradient(x1:0, y1:1, x2:0, y2:0, stop:0 #f9b158, stop:1 #ffe189)/*上边框渐变色*/ 273 | qlineargradient(x1:0, y1:0, x2:1, y2:0, stop:0 #f9b158, stop:1 #ffe189)/*右边框渐变色*/ 274 | qlineargradient(x1:0, y1:0, x2:0, y2:1, stop:0 #f9b158, stop:1 #ffe189)/*下边框渐变色*/ 275 | qlineargradient(x1:1, y1:0, x2:0, y2:0, stop:0 #f9b158, stop:1 #ffe189);/*左边框渐变色*/ 276 | } 277 | 278 | /*为QCommandLinkButton设置通用属性*/ 279 | QCommandLinkButton 280 | { 281 | border: none;/*边框*/ 282 | background: none; 283 | } 284 | 285 | /*/////////////////////////////////////////////////QCheckBox///////////////////////////////////////////*/ 286 | /*QCheckBox的公用属性设置*/ 287 | QCheckBox 288 | { 289 | spacing:5px;/*指示器与文字之间的距离*/ 290 | outline:none;/*表示foucs状态时取消虚线框*/ 291 | } 292 | 293 | /*QCheckBox指示器subcontrol属性设置*/ 294 | QCheckBox::indicator 295 | { 296 | width:15px;/*设置固定宽度,width height设置的宽高为content区宽高*/ 297 | height:15px;/*设置固定高度*/ 298 | } 299 | 300 | /*QCheckBox指示器选中时属性设置*/ 301 | QCheckBox::indicator:checked 302 | { 303 | image:url(:/qss/icon/checkbox_p.png);/*图片*/ 304 | } 305 | 306 | /*QCheckBox指示器未选中时属性设置*/ 307 | QCheckBox::indicator:unchecked 308 | { 309 | image:url(:/qss/icon/checkbox.png);/*图片*/ 310 | } 311 | 312 | /*QCheckBox指示器未选中时且hover时属性设置*/ 313 | QCheckBox::indicator:unchecked:hover 314 | { 315 | image:url(:/qss/icon/checkbox_h.png);/*图片*/ 316 | 317 | } 318 | 319 | /*/////////////////////////////////////////////////QRadioButton///////////////////////////////////////////*/ 320 | /*QRadioButton公用属性设置*/ 321 | QRadioButton 322 | { 323 | spacing:5px;/*指示器与文字之间的距离*/ 324 | outline:none;/*表示foucs状态时取消虚线框*/ 325 | } 326 | 327 | /*QRadioButton指示器选中时属性设置*/ 328 | QRadioButton::indicator 329 | { 330 | width:15px;/*设置固定宽度,width height设置的宽高为content区宽高*/ 331 | height:15px;/*设置固定宽度*/ 332 | } 333 | 334 | /*QRadioButton指示器选中时属性设置*/ 335 | QRadioButton::indicator:checked 336 | { 337 | image:url(:/qss/icon/radio_p.png);/**/ 338 | } 339 | 340 | /*QRadioButton指示器未选中时属性设置*/ 341 | QRadioButton::indicator:unchecked 342 | { 343 | image:url(:/qss/icon/radio.png);/**/ 344 | } 345 | 346 | /*QRadioButton指示器未选中掠过时属性设置*/ 347 | QRadioButton::indicator:unchecked:hover 348 | { 349 | image:url(:/qss/icon/radio_h.png);/**/ 350 | 351 | } 352 | 353 | /*/////////////////////////////////////////////////QLineEdit///////////////////////////////////////////*/ 354 | /*QLineEdit公用属性设置*/ 355 | QLineEdit 356 | { 357 | padding:1px; 358 | padding-left:4px; 359 | border: 1px solid #aaaaaa; 360 | background: white; 361 | selection-background-color: #3399ff; 362 | } 363 | 364 | 365 | /*QLineEdit获得焦点时的属性设置,主要为光晕边框 366 | 这里带了.,所以该属性仅对QLineEdit直接类对象生效,这样做的目的在于,可编辑QTableWidget编辑item时的编辑框不带边框*/ 367 | .QLineEdit:focus1 368 | { 369 | padding:0px;/*padding,这里边框为2px为了不引起content尺寸变化padding设置为0*/ 370 | padding-left:3px; 371 | border-width:2px;/*边框宽度*/ 372 | border-style:solid;/*边框类型*/ 373 | /*用渐变色可以营造光晕边框效果*/ 374 | border-color:qlineargradient(x1:0, y1:1, x2:0, y2:0, stop:0 #f9b158, stop:1 #ffe189)/*上边框渐变色*/ 375 | qlineargradient(x1:0, y1:0, x2:1, y2:0, stop:0 #f9b158, stop:1 #ffe189)/*右边框渐变色*/ 376 | qlineargradient(x1:0, y1:0, x2:0, y2:1, stop:0 #f9b158, stop:1 #ffe189)/*下边框渐变色*/ 377 | qlineargradient(x1:1, y1:0, x2:0, y2:0, stop:0 #f9b158, stop:1 #ffe189);/*左边框渐变色*/ 378 | } 379 | 380 | QLineEdit:read-only 381 | { 382 | color: #787878; 383 | } 384 | 385 | /*/////////////////////////////////////////////////QPlainTextEdit///////////////////////////////////////////*/ 386 | QPlainTextEdit 387 | { 388 | padding:0px; 389 | border: 1px solid #aaaaaa; 390 | background: white; 391 | selection-background-color: #3399ff; 392 | } 393 | 394 | QPlainTextEdit:read-only 395 | { 396 | color: #787878; 397 | } 398 | 399 | /*/////////////////////////////////////////////////QTextEdit///////////////////////////////////////////*/ 400 | QTextEdit 401 | { 402 | padding:0px; 403 | border: 1px solid #aaaaaa; 404 | background: white; 405 | selection-background-color: #3399ff; 406 | } 407 | 408 | 409 | /*/////////////////////////////////////////////////QComboBox///////////////////////////////////////////*/ 410 | /*QComboBox设置公用属性*/ 411 | QComboBox 412 | { 413 | border: 1px solid #aaaaaa;/*边框*/ 414 | padding:2px 18px 2px 3px;/*内边距,有偏移18px为drop-down按钮留出空间,所以subcontrol-origin属性须设为padding*/ 415 | min-width:36px;/*最小宽度为6em em和px一样为长度单位。em表示对应字体M的宽度。M为大写字母的最大宽度*/ 416 | } 417 | 418 | /*QLineEdit获得焦点时的属性设置,设置边框为光晕边框*/ 419 | QComboBox:focus1 420 | { 421 | padding:1px 17px 1px 2px;/*padding,这里边框为2px为了不引起content尺寸变化padding均减1*/ 422 | border-width:2px; 423 | border-style:solid; 424 | border-color:qlineargradient(x1:0, y1:1, x2:0, y2:0, stop:0 #64bff0, stop:1 #bae3f7)/*上边框渐变色*/ 425 | qlineargradient(x1:0, y1:0, x2:1, y2:0, stop:0 #64bff0, stop:1 #bae3f7)/*右边框渐变色*/ 426 | qlineargradient(x1:0, y1:0, x2:0, y2:1, stop:0 #64bff0, stop:1 #bae3f7)/*下边框渐变色*/ 427 | qlineargradient(x1:1, y1:0, x2:0, y2:0, stop:0 #64bff0, stop:1 #bae3f7);/*左边框渐变色*/ 428 | } 429 | 430 | /*设置drop-down按钮上的箭头图片*/ 431 | QComboBox::down-arrow 432 | { 433 | image:url(:/qss/icon/downarrow.png); 434 | } 435 | 436 | /*设置drop-down按钮属性,自定义combox的重头戏。必须设置*/ 437 | QComboBox::drop-down { 438 | width:15px;/*drop-down按钮宽度*/ 439 | background: qlineargradient(x1:0, y1:0, x2:0, y2:1, stop:0 #ffffff, stop:0.8 #eeeeee);/*drop-down按钮渐变背景色*/ 440 | subcontrol-origin: padding;/*drop-down按钮绘制位置依据父控件设置的padding决定*/ 441 | subcontrol-position: right top;/*drop-down按钮相对父控件位置*/ 442 | border-left:1px solid #aaaaaa;/*drop-down左边框*/ 443 | } 444 | 445 | /*设置QComboBox的:下拉时的视图属性。注意这不是设置的视图项,而是视图项主城的视图 446 | 子孙窗口部件,用空格隔开。*/ 447 | QComboBox QAbstractItemView 448 | { 449 | border: 1px solid #aaaaaa;/*边框*/ 450 | selection-background-color: #73c5f1;/*选中背景*/ 451 | outline:none;/*去掉选中时的虚线框*/ 452 | } 453 | 454 | /*/////////////////////////////////////////////////QGroupBox///////////////////////////////////////////*/ 455 | /*QGroupBox公用属性设置*/ 456 | QGroupBox { 457 | background: none;/*背景透明*/ 458 | border: 1px solid #aaaaaa;/*边框*/ 459 | border-radius: 5px;/*边框圆角*/ 460 | margin-top: 2ex; /* 为title绘制留出空间,以下title子控制器的subcontrol-origin设置为margin */ 461 | } 462 | 463 | /*QGroupBox title子控制器属性设置*/ 464 | QGroupBox::title 465 | { 466 | color:#3399ff;/*文本颜色*/ 467 | left:10px;/*子控制器相对于父控件的精确定位*/ 468 | subcontrol-origin: margin;/*子控制器绘制起始区域*/ 469 | subcontrol-position: top left; /*子控制器于父控件的相对位置*/ 470 | padding: 0px 2px;/*title文字左右padding设置使边框线条与title文字有间隔距离*/ 471 | background: none;/*背景透明*/ 472 | } 473 | 474 | /*/////////////////////////////////////////////////QProgressBar///////////////////////////////////////////*/ 475 | /*QProgressBar公用属性设置*/ 476 | QProgressBar 477 | { 478 | border: 1px solid #aaaaaa;/*边框*/ 479 | background: white;/*qlineargradient(x1:0, y1:0, x2:1, y2:1, stop:0 #eeeeee, stop:1 #ffffff);渐变背景*/ 480 | border-radius: 4px;/*边框圆角*/ 481 | text-align:center;/*文本对齐*/ 482 | } 483 | 484 | /*chunk子控制器,指进度条内一块块依次向右的进度小块*/ 485 | QProgressBar::chunk 486 | { 487 | background: qlineargradient(x1:0, y1:0, x2:0, y2:1, stop:0 #73c5f1, stop:0.6 #bde4f8, stop:1 #73c5f1); /*进度小块背景*/ 488 | width: 6px;/*进度小块宽度*/ 489 | margin: 0.5px;/*进度小块margin设置为0.5px以上可以隔开进度小块。隔开距离为2*margin 。设置为0.5以下进度小块连在一起*/ 490 | } 491 | 492 | /*/////////////////////////////////////////////////QSlider///////////////////////////////////////////*/ 493 | /*QSlider水平凹槽属性设置,未设置背景因为它反正会被add-page subControl覆盖*/ 494 | QSlider::groove:horizontal 495 | { 496 | border: 1px solid #aaaaaa;/*边框*/ 497 | height: 6px; /*水平凹槽高度*/ 498 | } 499 | 500 | /*QSlider水平滑块属性设置*/ 501 | QSlider::handle:horizontal 502 | { 503 | background: qlineargradient(x1:0, y1:0, x2:0, y2:1, stop:1 #666666, stop:0.5 #dddddd);/*渐变背景*/ 504 | border: 1px solid #5c5c5c;/*边框*/ 505 | width: 6px;/*滑块宽度*/ 506 | margin: -6px 0;/*通过设置margin上下margin为-6px,使得滑块高度比凹槽高度高12px。*/ 507 | border-radius: 4px;/*圆角边框*/ 508 | } 509 | 510 | /*通过add-page subControl设置未划过部分的背景*/ 511 | QSlider::add-page:horizontal 512 | { 513 | border: 1px solid #aaaaaa; 514 | background: white;/*qlineargradient(x1:0, y1:0, x2:1, y2:1, stop:0 #eeeeee, stop:1 #ffffff);*/ 515 | } 516 | 517 | /*通过sub-page subControl设置划过部分的背景*/ 518 | QSlider::sub-page:horizontal 519 | { 520 | border: 1px solid #aaaaaa; 521 | background: qlineargradient(x1:0, y1:0, x2:1, y2:0, stop:0 #73c5f1, stop:0.6 #bde4f8, stop:1 #73c5f1); 522 | } 523 | 524 | /*垂直滑动条:大同小异*/ 525 | QSlider::groove:vertical 526 | { 527 | border: 1px solid #aaaaaa; 528 | width: 6px; 529 | } 530 | 531 | QSlider::handle:vertical 532 | { 533 | background: qlineargradient(x1:0, y1:0, x2:0, y2:1, stop:1 #666666, stop:0.4 #dddddd);/*渐变背景*/ 534 | border: 1px solid #5c5c5c; 535 | height: 6px; 536 | margin: 0px -6px; 537 | border-radius: 4px; 538 | } 539 | 540 | QSlider::add-page:vertical 541 | { 542 | border: 1px solid #aaaaaa; 543 | background: qlineargradient(x1:0, y1:0, x2:0, y2:1, stop:0 #73c5f1, stop:0.6 #bde4f8, stop:1 #73c5f1); 544 | } 545 | 546 | QSlider::sub-page:vertical 547 | { 548 | border: 1px solid #aaaaaa; 549 | background: white;/*qlineargradient(x1:0, y1:0, x2:1, y2:1, stop:0 #eeeeee, stop:1 #ffffff);*/ 550 | } 551 | 552 | 553 | /*/////////////////////////////////////////////////QScrollBar///////////////////////////////////////////*/ 554 | /*水平滚动条公用属性设置*/ 555 | QScrollBar:horizontal 556 | { 557 | border-top: 1px solid #aaaaaa;/*边框*/ 558 | /*background: qlineargradient(x1:0, y1:0, x2:0, y2:1, stop:0 #eeeeee, stop:0.8 #ffffff);渐变背景,也是滑轨背景*/ 559 | background:white; 560 | height: 16px;/*水平滚动条高度*/ 561 | margin: 0px 16px 0 16px;/*水平滚动条margin,左右留出空间给add-line按钮和sub-line按钮*/ 562 | } 563 | 564 | /*水平滚动条滑块公用属性设置*/ 565 | QScrollBar::handle:horizontal 566 | { 567 | /*background: qlineargradient(x1:0, y1:0, x2:0, y2:1, stop:0 #73c5f1, stop:0.6 #bde4f8, stop:1 #73c5f1);背景*/ 568 | background: qlineargradient(x1:0, y1:0, x2:0, y2:1, stop:0 #ffffff, stop:0.8 #eeeeee);/*渐变背景色*/ 569 | min-width: 20px;/*最小宽度,滑块宽度自动调整但须设置一个最小宽度*/ 570 | border-radius: 0px;/**/ 571 | border-left:1px solid #aaaaaa; 572 | border-right:1px solid #aaaaaa; 573 | } 574 | 575 | /*水平滚动条滑块被掠过时*/ 576 | QScrollBar::handle:horizontal:hover 577 | { 578 | /*background: qlineargradient(x1:0, y1:0, x2:0, y2:1, stop:0 #90d9fe, stop:0.6 #e2f3fc, stop:1 #90d9fe);渐变背景*/ 579 | background: qlineargradient(x1:0, y1:0, x2:0, y2:1, stop:0.2 #eeeeee, stop:1 #ffffff);/*渐变背景色*/ 580 | } 581 | 582 | /*水平滚动条滑块被按压时*/ 583 | QScrollBar::handle:horizontal:pressed 584 | { 585 | /*background: qlineargradient(x1:0, y1:0, x2:0, y2:1, stop:0 #60c8fd, stop:0.6 #bde4f8, stop:1 #60c8fd);渐变背景*/ 586 | background: qlineargradient(x1:0, y1:0, x2:0, y2:1, stop:0 #ffffff, stop:0.8 #eeeeee);/*渐变背景色*/ 587 | } 588 | 589 | /*水平滚动条sub-line(增加一行)按钮*/ 590 | QScrollBar::add-line:horizontal 591 | { 592 | border-top: 1px solid #aaaaaa;/*边框*/ 593 | border-left: 1px solid #aaaaaa;/*边框*/ 594 | border-right: 1px solid #aaaaaa;/*边框*/ 595 | background: qlineargradient(x1:0, y1:0, x2:0, y2:1, stop:0 #ffffff, stop:0.8 #eeeeee);/*渐变背景*/ 596 | width: 16px;/*宽度,跟父控件margin匹配*/ 597 | subcontrol-position: right;/*sub-line按钮相对于父控件位置设置*/ 598 | subcontrol-origin: margin;/*sub-line按钮绘制空间,之前父控件设置了margin为sub-line留出了控件*/ 599 | } 600 | 601 | /*水平滚动条add-line(增加一行)按钮被掠过时*/ 602 | QScrollBar::add-line:horizontal:hover 603 | { 604 | background: qlineargradient(x1:0, y1:0, x2:0, y2:1, stop:0.4 #ffffff, stop:1 #eeeeee);/*渐变背景*/ 605 | } 606 | 607 | /*水平滚动条add-line(增加一行)按钮被按压时*/ 608 | QScrollBar::add-line:horizontal:pressed 609 | { 610 | background: qlineargradient(x1:0, y1:0, x2:0, y2:1, stop:0 #ffffff, stop:0.4 #eeeeee);/*渐变背景*/ 611 | } 612 | 613 | /*水平滚动条sub-line(减少一行)按钮*/ 614 | QScrollBar::sub-line:horizontal 615 | { 616 | border-top: 1px solid #aaaaaa;/*边框*/ 617 | border-right: 1px solid #aaaaaa;/*边框*/ 618 | background: qlineargradient(x1:0, y1:0, x2:0, y2:1, stop:0 #ffffff, stop:0.8 #eeeeee);/*渐变背景*/ 619 | width: 16px;/*宽度,跟父控件margin匹配*/ 620 | subcontrol-position: left;/*sub-line按钮相对于父控件位置设置*/ 621 | subcontrol-origin: margin;/*sub-line按钮绘制空间,之前父控件设置了margin为sub-line留出了控件*/ 622 | } 623 | 624 | /*水平滚动条sub-line(减少一行)按钮hover时*/ 625 | QScrollBar::sub-line:horizontal:hover 626 | { 627 | background: qlineargradient(x1:0, y1:0, x2:0, y2:1, stop:0.4 #ffffff, stop:1 #eeeeee);/*渐变背景*/ 628 | } 629 | 630 | /*水平滚动条sub-line(减少一行)按钮被按压时*/ 631 | QScrollBar::sub-line:horizontal:pressed 632 | { 633 | background: qlineargradient(x1:0, y1:0, x2:0, y2:1, stop:0 #ffffff, stop:0.4 #eeeeee);/*渐变背景*/ 634 | } 635 | 636 | /*水平滚动条左箭头设置图像(在add-line中居中显示)*/ 637 | QScrollBar:left-arrow:horizontal 638 | { 639 | image:url(:/qss/icon/hor_scroll_left_arrow.png);/*箭头图像*/ 640 | } 641 | 642 | /*水平滚动条右箭头设置图像(在sub-line中居中显示)*/ 643 | QScrollBar::right-arrow:horizontal 644 | { 645 | image:url(:/qss/icon/hor_scroll_right_arrow.png);/*箭头图像*/ 646 | } 647 | 648 | /*水平滚动条add-page,sub-page指单击滑轨时滚动一页。可以为add-page,sub-page设置hover,pressed的背景 */ 649 | QScrollBar::add-page:horizontal, QScrollBar::sub-page:horizontal 650 | { 651 | background: none;/*不设置add-page,sub-page背景*/ 652 | } 653 | 654 | 655 | /*垂直滚动条,大同小异*/ 656 | QScrollBar:vertical 657 | { 658 | border-left: 1px solid #aaaaaa; 659 | /*background: qlineargradient(x1:0, y1:0, x2:1, y2:0, stop:0 #eeeeee, stop:0.8 #ffffff);*/ 660 | background:white; 661 | width: 16px; 662 | margin: 16px 0px 16px 0px; 663 | } 664 | 665 | QScrollBar::handle:vertical 666 | { 667 | /*background: qlineargradient(x1:0, y1:0, x2:1, y2:0, stop:0 #73c5f1, stop:0.6 #bde4f8, stop:1 #73c5f1);渐变背景色*/ 668 | background: qlineargradient(x1:0, y1:0, x2:1, y2:0, stop:0 #ffffff, stop:0.8 #eeeeee);/*渐变背景色*/ 669 | min-height: 20px; 670 | border-radius: 0px; 671 | border-top:1px solid #aaaaaa; 672 | border-bottom:1px solid #aaaaaa; 673 | } 674 | 675 | QScrollBar::handle:vertical:hover 676 | { 677 | /*background: qlineargradient(x1:0, y1:0, x2:1, y2:0, stop:0 #90d9fe, stop:0.6 #e2f3fc, stop:1 #90d9fe);渐变背景*/ 678 | background: qlineargradient(x1:0, y1:0, x2:1, y2:0, stop:0.2 #eeeeee, stop:1 #ffffff);/*渐变背景色*/ 679 | } 680 | 681 | QScrollBar::handle:vertical:pressed 682 | { 683 | /*background: qlineargradient(x1:0, y1:0, x2:1, y2:0, stop:0 #60c8fd, stop:0.6 #bde4f8, stop:1 #60c8fd);渐变背景色*/ 684 | background: qlineargradient(x1:0, y1:0, x2:1, y2:0, stop:0 #ffffff, stop:0.8 #eeeeee);/*渐变背景色*/ 685 | } 686 | 687 | QScrollBar::add-line:vertical 688 | { 689 | border-left: 1px solid #aaaaaa; 690 | border-top: 1px solid #aaaaaa; 691 | border-bottom: 1px solid #aaaaaa; 692 | background: qlineargradient(x1:0, y1:0, x2:1, y2:0, stop:0 #ffffff, stop:0.8 #eeeeee); 693 | height: 16px; 694 | subcontrol-position: bottom; 695 | subcontrol-origin: margin; 696 | } 697 | 698 | QScrollBar::add-line:vertical:hover 699 | { 700 | background: qlineargradient(x1:0, y1:0, x2:1, y2:0, stop:0.4 #ffffff, stop:1 #eeeeee); 701 | } 702 | 703 | QScrollBar::add-line:vertical:pressed 704 | { 705 | background: qlineargradient(x1:0, y1:0, x2:1, y2:0, stop:0 #ffffff, stop:0.4 #eeeeee); 706 | } 707 | 708 | QScrollBar::sub-line:vertical 709 | { 710 | border-left: 1px solid #aaaaaa; 711 | border-bottom: 1px solid #aaaaaa; 712 | background: qlineargradient(x1:0, y1:0, x2:1, y2:0, stop:0 #ffffff, stop:0.8 #eeeeee); 713 | height: 16px; 714 | subcontrol-position: top; 715 | subcontrol-origin: margin; 716 | } 717 | 718 | QScrollBar::sub-line:vertical:hover 719 | { 720 | background: qlineargradient(x1:0, y1:0, x2:1, y2:0, stop:0.4 #ffffff, stop:1 #eeeeee); 721 | } 722 | 723 | QScrollBar::sub-line:vertical:pressed 724 | { 725 | background: qlineargradient(x1:0, y1:0, x2:1, y2:0, stop:0 #ffffff, stop:0.4 #eeeeee); 726 | } 727 | 728 | QScrollBar::down-arrow:vertical 729 | { 730 | image:url(:/qss/icon/ver_scroll_bottom_arrow.png); 731 | } 732 | 733 | QScrollBar::up-arrow:vertical 734 | { 735 | image:url(:/qss/icon/ver_scroll_top_arrow.png); 736 | } 737 | 738 | QScrollBar::add-page:vertical, QScrollBar::sub-page:vertical 739 | { 740 | background: none; 741 | } 742 | 743 | /* 744 | 一种更为简洁的滚动条 745 | QScrollBar:horizontal 746 | { 747 | background: #f2f2f2; 748 | height: 12px; 749 | } 750 | 751 | QScrollBar::handle:horizontal 752 | { 753 | background: #dddddd; 754 | min-width: 20px; 755 | border-radius: 6px; 756 | } 757 | 758 | QScrollBar::handle:horizontal:hover 759 | { 760 | background: #d0d0d0; 761 | } 762 | 763 | QScrollBar::handle:horizontal:pressed 764 | { 765 | background: #d0d0d0; 766 | } 767 | 768 | QScrollBar::add-line:horizontal, QScrollBar::sub-line:horizontal 769 | { 770 | background: none; 771 | } 772 | QScrollBar::add-page:horizontal, QScrollBar::sub-page:horizontal 773 | { 774 | background: none; 775 | } 776 | 777 | 778 | QScrollBar:vertical 779 | { 780 | background: #f2f2f2; 781 | width: 12px; 782 | } 783 | 784 | QScrollBar::handle:vertical 785 | { 786 | background: #dddddd; 787 | min-height: 20px; 788 | border-radius: 6px; 789 | } 790 | 791 | QScrollBar::handle:vertical:hover 792 | { 793 | background: #d0d0d0; 794 | } 795 | 796 | QScrollBar::handle:vertical:pressed 797 | { 798 | background: #d0d0d0; 799 | } 800 | 801 | QScrollBar::add-line:vertical, QScrollBar::sub-line:vertical 802 | { 803 | background: none; 804 | } 805 | QScrollBar::add-page:vertical, QScrollBar::sub-page:vertical 806 | { 807 | background: none; 808 | } 809 | 810 | */ 811 | 812 | /*/////////////////////////////////////////////////QTabWidget///////////////////////////////////////////*/ 813 | /*QTabWidget由子控制器pane和tab-bar组成。pane为tab页所在区域,tab-bar为tab标签栏所在区域*/ 814 | /*QTabWidget pane子控制器属性设置*/ 815 | QTabWidget::pane 816 | { 817 | border: 0px solid #aaaaaa; /*tab有边框pane就不要边框了*/ 818 | margin-top:-1px;/*设置margin-top为-1是为了让tab-bar遮掉pane的上边框*/ 819 | } 820 | 821 | /*QTabWidget tab-bar子控制器属性设置*/ 822 | QTabWidget::tab-bar 823 | { 824 | left: 3px; /*left表示子控制器距父控件左边的距离定位*/ 825 | } 826 | 827 | /*tab-bar子控制器(tab标签栏)又由tab标签组成,子控制器tab表示tab标签*/ 828 | QTabBar::tab 829 | { 830 | background: qlineargradient(x1:0, y1:0, x2:0, y2:1, stop:0 #eeeeee, stop:0.8 #dddddd);/*渐变背景色*/ 831 | border-left: 1px solid #aaaaaa;/*边框,不设置标签底部边框*/ 832 | border-right: 1px solid #aaaaaa;/**/ 833 | border-top: 1px solid #aaaaaa;/**/ 834 | border-top-left-radius: 6px;/**/ 835 | border-top-right-radius: 6px;/**/ 836 | min-width: 18ex;/**/ 837 | padding: 4px;/**/ 838 | } 839 | 840 | /*tab标签被选中或掠过时*/ 841 | QTabBar::tab:selected, QTabBar::tab:hover 842 | { 843 | background: qlineargradient(x1:0, y1:0, x2:0, y2:1, stop:0 #ffffff, stop:0.8 #eeeeee);/*渐变背景色*/ 844 | } 845 | 846 | /*tab标签被选中时*/ 847 | QTabBar::tab:selected 848 | { 849 | border-bottom: 3px solid #73c5f1;/*设置底部边框*/ 850 | margin-left: -4px;/*设置margin-top为-4px是为了扩大选中标签宽度,使得选中标签宽度大于未选中标签*/ 851 | margin-right: -4px;/**/ 852 | } 853 | 854 | /*tab标签未被选中时*/ 855 | QTabBar::tab:!selected 856 | { 857 | border-bottom: 1px solid #aaaaaa;/*设置底部边框*/ 858 | margin-top: 2px;/*设置margin-top为了压缩标签大小,使得未选中标签高度小于选中标签*/ 859 | } 860 | 861 | /*第一个tab标签被选中时*/ 862 | QTabBar::tab:first:selected 863 | { 864 | margin-left: 0px; /*左边不扩大宽度*/ 865 | } 866 | 867 | /*最后一个tab标签被选中时*/ 868 | QTabBar::tab:last:selected 869 | { 870 | margin-right: 0px;/*右边不扩大宽度*/ 871 | } 872 | 873 | /*只有一个tab标签时*/ 874 | QTabBar::tab:only-one 875 | { 876 | margin: 0px;/*不使用margin对标签大小作改变*/ 877 | } 878 | 879 | /*QTabBar上标签过多时出现的左右箭头QToolButton按钮属性设置*/ 880 | QTabBar QToolButton 881 | { 882 | border-radius: 6px; 883 | } 884 | 885 | /*QTabBar上标签过多时出现的左右箭头按钮箭头图片*/ 886 | QTabBar QToolButton::right-arrow 887 | { 888 | image:url(:/qss/icon/hor_scroll_right_arrow.png);/*箭头图像*/ 889 | } 890 | 891 | /*QTabBar上标签过多时出现的左右箭头按钮箭头图片*/ 892 | QTabBar QToolButton::left-arrow 893 | { 894 | image:url(:/qss/icon/hor_scroll_left_arrow.png);/*箭头图像*/ 895 | } 896 | 897 | 898 | /*/////////////////////////////////////////////////QCalendarWidget日历控件///////////////////////////////////////////*/ 899 | QCalendarWidget QToolButton 900 | { 901 | color:Black; 902 | } 903 | 904 | /*QCalendarWidget上左右箭头按钮箭头图片*/ 905 | QCalendarWidget QToolButton::right-arrow 906 | { 907 | image:url(:/qss/icon/hor_scroll_right_arrow.png);/*箭头图像*/ 908 | } 909 | 910 | /*QCalendarWidget上左右箭头按钮箭头图片*/ 911 | QCalendarWidget QToolButton::left-arrow 912 | { 913 | image:url(:/qss/icon/hor_scroll_left_arrow.png);/*箭头图像*/ 914 | } 915 | 916 | /*/////////////////////////////////////////////////QListView/QListWidget///////////////////////////////////////////*/ 917 | /*QListView公用属性设置*/ 918 | QListView 919 | { 920 | border:1px solid #aaaaaa;/*边框*/ 921 | selection-background-color: #73c5f1;/*选中背景*/ 922 | alternate-background-color:#e9e9e9;/*交替行背景色,代码中设置了交替行背景设有效时生效*/ 923 | outline:none;/*去掉选中时的虚线框*/ 924 | } 925 | 926 | QListView::item 927 | { 928 | min-height:24px;/*调整项高度*/ 929 | margin-left:40px; 930 | } 931 | 932 | /*/////////////////////////////////////////////////QTableView/QTableWidget///////////////////////////////////////////*/ 933 | /*QTableView公用属性设置*/ 934 | QTableView 935 | { 936 | border:1px solid #aaaaaa;/*边框*/ 937 | background:#ffffff;/*背景*/ 938 | selection-background-color: #73c5f1;/*选中背景*/ 939 | alternate-background-color:#e9e9e9;/*交替行背景色,代码中设置了交替行背景设有效时生效*/ 940 | } 941 | 942 | /*QTableView的CornerButton区域设置*/ 943 | QTableView QTableCornerButton::section 944 | { 945 | background: qlineargradient(x1:0, y1:0, x2:0, y2:1, stop:0 #ffffff, stop:0.8 #eeeeee);/*渐变背景色*/ 946 | border: 1px outset #aaaaaa;/*边框 outset类型边框指右底边框比左上边框颜色深,可参见w3c border-style属性*/ 947 | } 948 | 949 | /*QTableView表头设置,设置表头所有位置的背景,而不是仅仅为section部分,包括垂直和水平表头*/ 950 | QTableView QHeaderView 951 | { 952 | background: #eeeeee;/*QHeaderView背景色*/ 953 | } 954 | 955 | /*QTableView表头section部分设置,包括垂直和水平表头*/ 956 | QTableView QHeaderView::section 957 | { 958 | background: qlineargradient(x1:0, y1:0, x2:0, y2:1, stop:0 #ffffff, stop:0.8 #eeeeee);/*渐变背景色*/ 959 | border: 1px outset #aaaaaa;/**/ 960 | padding:4px;/*调整表头高度*/ 961 | } 962 | 963 | QTableView::item 964 | { 965 | min-height:24px;/*调整项高度*/ 966 | } 967 | 968 | /*/////////////////////////////////////////////////QTreeView/QTreeWidget///////////////////////////////////////////*/ 969 | /*QTreeView公用属性设置*/ 970 | QTreeView 971 | { 972 | border:1px solid #aaaaaa;/*边框*/ 973 | show-decoration-selected: 1; 974 | background:#ffffff;/*背景*/ 975 | selection-background-color: #73c5f1;/*选中背景*/ 976 | alternate-background-color:#e9e9e9;/*交替行背景色,代码中设置了交替行背景设有效时生效*/ 977 | } 978 | 979 | /*QTreeView表头设置,设置表头所有位置的背景,而不是仅仅为section部分,包括垂直和水平表头*/ 980 | QTreeView QHeaderView 981 | { 982 | background: qlineargradient(x1:0, y1:0, x2:0, y2:1, stop:0 #ffffff, stop:0.8 #eeeeee);/*渐变背景色*/ 983 | } 984 | 985 | /*QTreeView表头section部分设置,包括垂直和水平表头*/ 986 | QTreeView QHeaderView::section 987 | { 988 | background: qlineargradient(x1:0, y1:0, x2:0, y2:1, stop:0 #ffffff, stop:0.8 #eeeeee);/*渐变背景色*/ 989 | border: 1px outset #aaaaaa;/**/ 990 | padding:4px;/*调整表头高度*/ 991 | } 992 | 993 | /*QTreeView item子控制器属性设置*/ 994 | QTreeView::item 995 | { 996 | min-height:30px;/*调整项高度*/ 997 | } 998 | 999 | /*QTreeView item子控制器掠过时属性设置*/ 1000 | QTreeView::item:hover 1001 | { 1002 | background: #c5e7f9; 1003 | } 1004 | 1005 | /*QTreeView item子控制器选中时属性设置*/ 1006 | QTreeView::item:selected 1007 | { 1008 | border: 0px solid #aaaaaa; 1009 | } 1010 | 1011 | /*QTreeView item子控制器选中且有焦点(此时字体颜色为白)时属性设置*/ 1012 | QTreeView::item:selected:active 1013 | { 1014 | background: #73c5f1; 1015 | } 1016 | 1017 | /*QTreeView item子控制器选中且无焦点(此时字体颜色为黑)时属性设置*/ 1018 | QTreeView::item:selected:!active 1019 | { 1020 | background: #73c5f1; 1021 | } 1022 | 1023 | /*branch没有合适的素材,暂时先不定制 1024 | QTreeView::branch { 1025 | background: palette(base); 1026 | } 1027 | 1028 | QTreeView::branch:has-siblings:!adjoins-item { 1029 | background: cyan; 1030 | } 1031 | 1032 | QTreeView::branch:has-siblings:adjoins-item { 1033 | background: red; 1034 | } 1035 | 1036 | QTreeView::branch:!has-children:!has-siblings:adjoins-item { 1037 | background: blue; 1038 | } 1039 | 1040 | QTreeView::branch:closed:has-children:has-siblings { 1041 | background: pink; 1042 | } 1043 | 1044 | QTreeView::branch:has-children:!has-siblings:closed { 1045 | background: gray; 1046 | } 1047 | 1048 | QTreeView::branch:open:has-children:has-siblings { 1049 | background: magenta; 1050 | } 1051 | 1052 | QTreeView::branch:open:has-children:!has-siblings { 1053 | background: green; 1054 | } 1055 | 1056 | QTreeView::branch:has-siblings:!adjoins-item { 1057 | border-image: url(vline.png) 0; 1058 | } 1059 | 1060 | QTreeView::branch:has-siblings:adjoins-item { 1061 | border-image: url(branch-more.png) 0; 1062 | } 1063 | 1064 | QTreeView::branch:!has-children:!has-siblings:adjoins-item { 1065 | border-image: url(branch-end.png) 0; 1066 | } 1067 | 1068 | QTreeView::branch:has-children:!has-siblings:closed, 1069 | QTreeView::branch:closed:has-children:has-siblings { 1070 | border-image: none; 1071 | image: url(branch-closed.png); 1072 | } 1073 | 1074 | QTreeView::branch:open:has-children:!has-siblings, 1075 | QTreeView::branch:open:has-children:has-siblings { 1076 | border-image: none; 1077 | image: url(branch-open.png); 1078 | } 1079 | */ 1080 | 1081 | /*/////////////////////////////////////////////////QMenuBar///////////////////////////////////////////*/ 1082 | /*菜单栏公用属性设置*/ 1083 | QMenuBar 1084 | { 1085 | border-bottom:1px solid #aaaaaa; 1086 | /*background: qlineargradient(x1:0, y1:1, x2:0, y2:0, stop:0.2 #dddddd, stop:1 #ffffff);渐变背景色*/ 1087 | background:#f2f2f2; 1088 | } 1089 | 1090 | /*菜单栏item子控制器(菜单项)属性设置*/ 1091 | QMenuBar::item 1092 | { 1093 | spacing: 3px; /* 设置菜单项之间空隙*/ 1094 | padding: 2px 10px;/*通过padding设置菜单项之间空隙和菜单栏高度*/ 1095 | background: transparent;/* 菜单项目本身背景透明*/ 1096 | border-radius: 1px;/*菜单项的圆角边框 */ 1097 | } 1098 | 1099 | /* 菜单栏item子控制器(菜单项)被选中时(菜单中的被选中即为被掠过,此时不弹出菜单项目列表) */ 1100 | QMenuBar::item:selected 1101 | { 1102 | background: qlineargradient(x1:0, y1:0, x2:0, y2:1, stop:0 #eeeeee, stop:0.8 #cccccc);/*渐变背景色*/ 1103 | } 1104 | 1105 | /* 菜单栏item子控制器(菜单项)被按压时(此时弹出菜单项目列表) */ 1106 | QMenuBar::item:pressed 1107 | { 1108 | background: qlineargradient(x1:0, y1:0, x2:0, y2:1, stop:0 #dddddd, stop:0.8 #bbbbbb);/*渐变背景色*/ 1109 | } 1110 | 1111 | 1112 | /*/////////////////////////////////////////////////QMenu///////////////////////////////////////////*/ 1113 | /*菜单项目列表(就是那个下拉列表)属性设置*/ 1114 | QMenu 1115 | { 1116 | background-color: white; /* 背景色 */ 1117 | border: 1px solid #aaaaaa;/* 边框 */ 1118 | } 1119 | 1120 | /*菜单项目列表item子控制器(菜单项目列表中菜单项目,注意item子控制器不包括图表和指示器,所以该子控制器影响的只有)属性设置*/ 1121 | QMenu::item 1122 | { 1123 | background-color: transparent;/*背景色透明*/ 1124 | padding:4px 26px 4px 26px;/*通过菜单项目padding属性调整菜单项目中文字位置*/ 1125 | } 1126 | 1127 | /*菜单项目列表item子控制器被选中(菜单中的被选中即为被掠过)时属性设置*/ 1128 | QMenu::item:selected 1129 | { 1130 | background-color: #73c5f1;/*设置背景色*/ 1131 | } 1132 | 1133 | /*菜单项目列表separator子控制器属性设置,即对菜单项目列表中的分隔条设置*/ 1134 | QMenu::separator 1135 | { 1136 | height: 1px; 1137 | background: #AAAAAA; 1138 | margin-left: 25px;/*左右留空*/ 1139 | margin-right: 5px; 1140 | } 1141 | 1142 | /*菜单项目列表right-arrow子控制器属性设置,即对菜单项目列表中的二级菜单的箭头设置*/ 1143 | QMenu::right-arrow 1144 | { 1145 | right:5px;/*调整箭头位置*/ 1146 | image:url(:/qss/icon/hor_scroll_right_arrow.png);/*箭头图像*/ 1147 | } 1148 | 1149 | /*菜单项目列表icon子控制器属性设置,即对菜单项目中图标的设置,但好像很多属性都不起作用如边框、背景、大小等,何解?*/ 1150 | QMenu::icon 1151 | { 1152 | position:relative;/*position指示:调整subcontrol位置的属性top left bottom right设置距离为相对subcontrol自身(relative)还是相对父控件(absolut)。默认为relative*/ 1153 | left: 5px;/*调整图表位置*/ 1154 | } 1155 | 1156 | 1157 | /*菜单项目列表indicator子控制器属性设置,即对菜单项目中指示器(包括checkable menu item前面的复选框、 1158 | exclusive checkable menu item前面的那个单选框)的设置,但好像很多属性都不起作用如边框、背景、大小等,何解?*/ 1159 | QMenu::indicator 1160 | { 1161 | position:relative;/*position指示:调整subcontrol位置的属性top left bottom right设置距离为相对subcontrol自身(relative)还是相对父控件(absolut)。默认为relative*/ 1162 | left: 5px;/*调整指示器位置*/ 1163 | } 1164 | 1165 | /*菜单项目非排他指示器即复选框为选中时的属性设置*/ 1166 | QMenu::indicator:non-exclusive:unchecked 1167 | { 1168 | image: url(:/qss/icon/checkbox.png); 1169 | } 1170 | 1171 | /*菜单项目非排他指示器即复选框为选中被掠过时的属性设置*/ 1172 | QMenu::indicator:non-exclusive:unchecked:selected 1173 | { 1174 | image: url(:/qss/icon/checkbox_h.png); 1175 | } 1176 | 1177 | /*菜单项目非排他指示器即复选框为选中时的属性设置*/ 1178 | QMenu::indicator:non-exclusive:checked 1179 | { 1180 | image: url(:/qss/icon/checkbox_p.png); 1181 | } 1182 | 1183 | /*菜单项目非排他指示器即复选框为选中被掠过时的属性设置*/ 1184 | QMenu::indicator:non-exclusive:checked:selected 1185 | { 1186 | image: url(:/qss/icon/checkbox_p.png); 1187 | } 1188 | 1189 | 1190 | /* 菜单项目排他指示器属性设置,大同小异 */ 1191 | QMenu::indicator:exclusive:unchecked 1192 | { 1193 | image: url(:/qss/icon/radio.png); 1194 | } 1195 | 1196 | QMenu::indicator:exclusive:unchecked:selected 1197 | { 1198 | image: url(:/qss/icon/radio_h.png); 1199 | } 1200 | 1201 | QMenu::indicator:exclusive:checked 1202 | { 1203 | image: url(:/qss/icon/radio_p.png); 1204 | } 1205 | 1206 | QMenu::indicator:exclusive:checked:selected 1207 | { 1208 | image: url(:/qss/icon/radio_p.png); 1209 | } 1210 | 1211 | 1212 | /*/////////////////////////////////////////////////QToolButton///////////////////////////////////////////*/ 1213 | /*QToolButton:工具栏上按钮或单独的工具按钮(单独工具按钮可弹出popupmenu)*/ 1214 | /**/ 1215 | /*QToolButton公用属性设置*/ 1216 | QToolButton 1217 | { 1218 | min-height:20px;/*最小宽度*/ 1219 | border: 1px solid #aaaaaa;/*边框*/ 1220 | border-radius: 4px;/*QToolButton与QPushButton基本一致,但这里设置的边框圆角不一致*/ 1221 | background: qlineargradient(x1:0, y1:0, x2:0, y2:1, stop:0 #ffffff, stop:0.8 #eeeeee);/*渐变背景色*/ 1222 | outline:none;/*表示foucs状态时取消虚线框*/ 1223 | } 1224 | 1225 | /*QToolButton类型为DelayPopup时为menu-indicator子控制器留出空间 1226 | DelayPopup表示持续按压按钮可弹出菜单*/ 1227 | QToolButton[popupMode="0"] 1228 | { 1229 | padding-right: 4px; /*用padding留出空间,初始subcontrol-origin属性要为padding*/ 1230 | } 1231 | 1232 | /*QToolButton类型为MenuButtonPopup时为menu-button子控制器留出空间 1233 | MenuButtonPopup表示点击menu-button子控制器可弹出菜单*/ 1234 | QToolButton[popupMode="1"] 1235 | { 1236 | padding-right: 18px; /*用padding留出空间,初始subcontrol-origin属性要为padding*/ 1237 | } 1238 | 1239 | /*QToolButton类型为InstantPopup时为menu-indicator子控制器留出空间 1240 | MenuButtonPopup表示点击QToolButton即可立即弹出菜单,Instant表示立即意思*/ 1241 | QToolButton[popupMode="2"] 1242 | { 1243 | padding-right: 4px;/*用padding留出空间,初始subcontrol-origin属性要为padding*/ 1244 | } 1245 | 1246 | /*QToolButton pressed伪状态时属性设置,注意hover伪状态设置一定要在pressed伪状态之前!!!!!!!!!!*/ 1247 | QToolButton:hover 1248 | { 1249 | background: qlineargradient(x1:0, y1:0, x2:0, y2:1, stop:0 #eeeeee, stop:0.8 #ffffff);/*渐变背景色*/ 1250 | } 1251 | 1252 | /*QToolButton pressed伪状态时属性设置,注意hover伪状态设置一定要在pressed伪状态之前!!!!!!!!!!*/ 1253 | QToolButton:pressed 1254 | { 1255 | background: qlineargradient(x1:0, y1:0, x2:0, y2:1, stop:0 #ffffff, stop:0.8 #dddddd);/*渐变背景色*/ 1256 | } 1257 | 1258 | /*QToolButton menu-button子控制器属性设置 1259 | menu-button子控制器仅对MenuButtonPopup类型QToolButton生效*/ 1260 | QToolButton::menu-button 1261 | { 1262 | border-left: 1px solid #aaaaaa;/*设置左边边框即可*/ 1263 | border-top-right-radius: 4px;/*设置右上边框圆角,与QToolButton自身圆角保持一致*/ 1264 | border-bottom-right-radius: 4px;/*设置右小边框圆角,与QToolButton自身圆角保持一致*/ 1265 | width: 16px;/*设置menu-button宽度,注意与QToolButton的padding-right属性值匹配*/ 1266 | } 1267 | 1268 | /*QToolButton menu-arrow子控制器属性设置 1269 | menu-arrow子控制器仅对MenuButtonPopup类型QToolButton生效,它为menu-button箭头*/ 1270 | QToolButton::menu-arrow 1271 | { 1272 | position:relative;/*position指示:调整subcontrol位置的属性top left bottom right设置距离为相对subcontrol自身(relative)还是相对父控件(absolut)。默认为relative*/ 1273 | top: 1px; /*顶部相对偏移1px,调整menu-arrow相对父控件位置*/ 1274 | right: 1px; /*右边相对偏移1px,调整menu-arrow相对父控件位置*/ 1275 | image:url(:/qss/icon/ver_scroll_bottom_arrow.png);/*箭头图片*/ 1276 | } 1277 | 1278 | /*QToolButton menu-arrow子控制器在菜单展开式的属性设置 1279 | menu-arrow子控制器仅对MenuButtonPopup类型QToolButton生效,它为menu-button箭头*/ 1280 | QToolButton::menu-arrow:open 1281 | { 1282 | top: 2px; /*顶部偏移1px,让箭头有下沉效果*/ 1283 | } 1284 | 1285 | /*QToolButton menu-indicator子控制器属性设置 1286 | menu-indicator子控制器仅对MenuButtonPopup和InstantPopup类型QToolButton生效,它表示按钮拥有菜单的指示*/ 1287 | QToolButton::menu-indicator 1288 | { 1289 | image:url(:/qss/icon/ver_scroll_bottom_arrow.png);/*箭头图片*/ 1290 | width:7px;/*menu-indicator宽度*/ 1291 | height:7px;/*menu-indicator高度*/ 1292 | padding:0px 2px;/*调整menu-indicator位置*/ 1293 | } 1294 | 1295 | /*/////////////////////////////////////////////////QToolBar///////////////////////////////////////////*/ 1296 | /*QToolBar公用属性设置*/ 1297 | QToolBar 1298 | { 1299 | spacing:2px;/*调整工具栏按钮间距离*/ 1300 | background:#f2f2f2;/*设置背景色与主窗口背景一致,这样在拖动时就不会露出原来背景色*/ 1301 | } 1302 | 1303 | /*QToolBar handle子控制器(就是那个工具栏拖动按钮)属性设置 */ 1304 | QToolBar::handle 1305 | { 1306 | /*保存默认即可*/ 1307 | } 1308 | 1309 | /*QToolBar separator子控制器(就是工具栏之间风格条)属性设置 */ 1310 | QToolBar::separator 1311 | { 1312 | /*保存默认即可*/ 1313 | } 1314 | 1315 | /*由于QToolButton的属性对QToolBar上button属性的影响不知道怎么分离, 1316 | 所以QToolBar上按钮效果要完全自己定制,其实qt本身实现的XP系统上玻璃覆盖效果不错*/ 1317 | /*QToolBar上按钮属性设置*/ 1318 | QToolBar QToolButton 1319 | { 1320 | margin-bottom:2px;/*调整按钮大小,防止QToolButton hover时遮住QToolBar自身边框*/ 1321 | border: none;/*去掉边框*/ 1322 | background:transparent;/*设置normal状态下背景色为透明色*/ 1323 | border-radius: 4px;/*边框圆角*/ 1324 | } 1325 | 1326 | /*/////////////////////////////////////////////////QToolTip///////////////////////////////////////////*/ 1327 | /*QToolTip(提示条)公用属性设置*/ 1328 | QToolTip 1329 | { 1330 | /*background:#f4f4f4;*/ 1331 | border: 1px solid #aaaaaa;/*边框*/ 1332 | padding: 1px;/*调整大小*/ 1333 | border-radius: 0px;/*边框圆角*/ 1334 | background:#fafafa; 1335 | opacity: 240;/*不透明度,255时不透明*/ 1336 | } 1337 | 1338 | /*/////////////////////////////////////////////////QSpinBox///////////////////////////////////////////*/ 1339 | QSpinBox 1340 | { 1341 | min-height:20px; 1342 | padding-right: 15px; 1343 | border: 1px solid #aaaaaa;/*边框*/ 1344 | min-width:1em;/*最小宽度为6em em和px一样为长度单位。em表示对应字体M的宽度。M为大写字母的最大宽度*/ 1345 | background:white; 1346 | } 1347 | 1348 | QSpinBox::up-button 1349 | { 1350 | subcontrol-origin: padding; 1351 | subcontrol-position: top right; 1352 | background: qlineargradient(x1:0, y1:0, x2:0, y2:1, stop:0 #ffffff, stop:0.8 #eeeeee);/*渐变背景色*/ 1353 | width: 15px; 1354 | border-left: 1px solid #aaaaaa; 1355 | border-bottom: 0px solid #aaaaaa; 1356 | } 1357 | 1358 | QSpinBox::up-button:hover 1359 | { 1360 | background: qlineargradient(x1:0, y1:0, x2:0, y2:1, stop:0 #eeeeee, stop:0.8 #ffffff);/*渐变背景色*/ 1361 | } 1362 | 1363 | QSpinBox::up-button:pressed 1364 | { 1365 | background: qlineargradient(x1:0, y1:0, x2:0, y2:1, stop:0 #ffffff, stop:0.8 #dddddd);/*渐变背景色*/ 1366 | } 1367 | 1368 | QSpinBox::up-arrow 1369 | { 1370 | image:url(:/qss/icon/ver_scroll_top_arrow.png); 1371 | width: 9px; 1372 | height: 9px; 1373 | } 1374 | 1375 | QSpinBox::up-arrow:disabled, QSpinBox::up-arrow:off 1376 | { 1377 | background: qlineargradient(x1:0, y1:0, x2:0, y2:1, stop:0 #ffffff, stop:0.6 #eeeeee);/*渐变背景色*/ 1378 | border: 0px solid #dddddd;/*边框*/ 1379 | } 1380 | 1381 | QSpinBox::down-button 1382 | { 1383 | subcontrol-origin: padding; 1384 | subcontrol-position: bottom right; 1385 | background: qlineargradient(x1:0, y1:1, x2:0, y2:0, stop:0 #ffffff, stop:0.8 #eeeeee);/*渐变背景色*/ 1386 | width: 15px; 1387 | border-left: 1px solid #aaaaaa; 1388 | border-top: 0px solid #aaaaaa; 1389 | } 1390 | 1391 | QSpinBox::down-button:hover 1392 | { 1393 | background: qlineargradient(x1:0, y1:1, x2:0, y2:0, stop:0 #eeeeee, stop:0.8 #ffffff);/*渐变背景色*/ 1394 | } 1395 | 1396 | QSpinBox::down-button:pressed 1397 | { 1398 | background: qlineargradient(x1:0, y1:1, x2:0, y2:0, stop:0 #ffffff, stop:0.8 #dddddd);/*渐变背景色*/ 1399 | } 1400 | 1401 | QSpinBox::down-arrow 1402 | { 1403 | image:url(:/qss/icon/ver_scroll_bottom_arrow.png); 1404 | width: 9px; 1405 | height: 9px; 1406 | } 1407 | 1408 | QSpinBox::down-arrow:disabled, 1409 | QSpinBox::down-arrow:off 1410 | { 1411 | background: qlineargradient(x1:0, y1:1, x2:0, y2:0, stop:0 #ffffff, stop:0.6 #eeeeee);/*渐变背景色*/ 1412 | border: 0px solid #dddddd;/*边框*/ 1413 | } 1414 | 1415 | 1416 | /*/////////////////////////////////////////////////QDoubleSpinBox///////////////////////////////////////////*/ 1417 | QDoubleSpinBox 1418 | { 1419 | min-height:20px; 1420 | padding-right: 15px; 1421 | border: 1px solid #aaaaaa;/*边框*/ 1422 | min-width:4em;/*最小宽度为6em em和px一样为长度单位。em表示对应字体M的宽度。M为大写字母的最大宽度*/ 1423 | } 1424 | 1425 | QDoubleSpinBox::up-button 1426 | { 1427 | subcontrol-origin: padding; 1428 | subcontrol-position: top right; /* position at the top right corner */ 1429 | background: qlineargradient(x1:0, y1:0, x2:0, y2:1, stop:0 #ffffff, stop:0.8 #eeeeee);/*渐变背景色*/ 1430 | width: 15px; 1431 | border-left: 1px solid #aaaaaa; 1432 | border-bottom: 0px solid #aaaaaa; 1433 | } 1434 | 1435 | QDoubleSpinBox::up-button:hover 1436 | { 1437 | background: qlineargradient(x1:0, y1:0, x2:0, y2:1, stop:0 #eeeeee, stop:0.8 #ffffff);/*渐变背景色*/ 1438 | } 1439 | 1440 | QDoubleSpinBox::up-button:pressed 1441 | { 1442 | background: qlineargradient(x1:0, y1:0, x2:0, y2:1, stop:0 #ffffff, stop:0.8 #dddddd);/*渐变背景色*/ 1443 | } 1444 | 1445 | QDoubleSpinBox::up-arrow 1446 | { 1447 | image:url(:/qss/icon/ver_scroll_top_arrow.png); 1448 | width: 9px; 1449 | height: 9px; 1450 | } 1451 | 1452 | QDoubleSpinBox::up-arrow:disabled, 1453 | QSpinBox::up-arrow:off 1454 | { 1455 | background: qlineargradient(x1:0, y1:0, x2:0, y2:1, stop:0 #ffffff, stop:0.6 #eeeeee);/*渐变背景色*/ 1456 | border: 1px solid #dddddd;/*边框*/ 1457 | } 1458 | 1459 | QDoubleSpinBox::down-button 1460 | { 1461 | subcontrol-origin: padding; 1462 | subcontrol-position: bottom right; 1463 | background: qlineargradient(x1:0, y1:1, x2:0, y2:0, stop:0 #ffffff, stop:0.8 #eeeeee);/*渐变背景色*/ 1464 | width: 15px; 1465 | border-left: 1px solid #aaaaaa; 1466 | border-top: 0px solid #aaaaaa; 1467 | } 1468 | 1469 | QDoubleSpinBox::down-button:hover 1470 | { 1471 | background: qlineargradient(x1:0, y1:1, x2:0, y2:0, stop:0 #eeeeee, stop:0.8 #ffffff);/*渐变背景色*/ 1472 | } 1473 | 1474 | QDoubleSpinBox::down-button:pressed 1475 | { 1476 | background: qlineargradient(x1:0, y1:1, x2:0, y2:0, stop:0 #ffffff, stop:0.8 #dddddd);/*渐变背景色*/ 1477 | } 1478 | 1479 | QDoubleSpinBox::down-arrow { 1480 | image:url(:/qss/icon/ver_scroll_bottom_arrow.png); 1481 | width: 9px; 1482 | height: 9px; 1483 | } 1484 | 1485 | QDoubleSpinBox::down-arrow:disabled, 1486 | QDoubleSpinBox::down-arrow:off 1487 | { 1488 | background: qlineargradient(x1:0, y1:1, x2:0, y2:0, stop:0 #ffffff, stop:0.6 #eeeeee);/*渐变背景色*/ 1489 | border: 1px solid #dddddd;/*边框*/ 1490 | } 1491 | 1492 | /*/////////////////////////////////////////////////QTimeEdit///////////////////////////////////////////*/ 1493 | QTimeEdit 1494 | { 1495 | min-height:20px; 1496 | padding-right: 15px; 1497 | border: 1px solid #aaaaaa;/*边框*/ 1498 | min-width:8em;/*最小宽度为6em em和px一样为长度单位。em表示对应字体M的宽度。M为大写字母的最大宽度*/ 1499 | } 1500 | 1501 | QTimeEdit::up-button 1502 | { 1503 | subcontrol-origin: padding; 1504 | subcontrol-position: top right; /* position at the top right corner */ 1505 | background: qlineargradient(x1:0, y1:0, x2:0, y2:1, stop:0 #ffffff, stop:0.8 #eeeeee);/*渐变背景色*/ 1506 | width: 15px; 1507 | border-left: 1px solid #aaaaaa; 1508 | border-bottom: 0px solid #aaaaaa; 1509 | } 1510 | 1511 | QTimeEdit::up-button:hover 1512 | { 1513 | background: qlineargradient(x1:0, y1:0, x2:0, y2:1, stop:0 #eeeeee, stop:0.8 #ffffff);/*渐变背景色*/ 1514 | } 1515 | 1516 | QTimeEdit::up-button:pressed 1517 | { 1518 | background: qlineargradient(x1:0, y1:0, x2:0, y2:1, stop:0 #ffffff, stop:0.8 #dddddd);/*渐变背景色*/ 1519 | } 1520 | 1521 | QTimeEdit::up-arrow 1522 | { 1523 | image:url(:/qss/icon/ver_scroll_top_arrow.png); 1524 | width: 9px; 1525 | height: 9px; 1526 | } 1527 | 1528 | QTimeEdit::up-arrow:disabled, 1529 | QTimeEdit::up-arrow:off 1530 | { 1531 | background: qlineargradient(x1:0, y1:0, x2:0, y2:1, stop:0 #ffffff, stop:0.6 #eeeeee);/*渐变背景色*/ 1532 | border: 1px solid #dddddd;/*边框*/ 1533 | } 1534 | 1535 | QTimeEdit::down-button 1536 | { 1537 | subcontrol-origin: padding; 1538 | subcontrol-position: bottom right; 1539 | background: qlineargradient(x1:0, y1:1, x2:0, y2:0, stop:0 #ffffff, stop:0.8 #eeeeee);/*渐变背景色*/ 1540 | width: 15px; 1541 | border-left: 1px solid #aaaaaa; 1542 | border-top: 0px solid #aaaaaa; 1543 | } 1544 | 1545 | QTimeEdit::down-button:hover 1546 | { 1547 | background: qlineargradient(x1:0, y1:1, x2:0, y2:0, stop:0 #eeeeee, stop:0.8 #ffffff);/*渐变背景色*/ 1548 | } 1549 | 1550 | QTimeEdit::down-button:pressed 1551 | { 1552 | background: qlineargradient(x1:0, y1:1, x2:0, y2:0, stop:0 #ffffff, stop:0.8 #dddddd);/*渐变背景色*/ 1553 | } 1554 | 1555 | QTimeEdit::down-arrow 1556 | { 1557 | image:url(:/qss/icon/ver_scroll_bottom_arrow.png); 1558 | width: 9px; 1559 | height: 9px; 1560 | } 1561 | 1562 | QTimeEdit::down-arrow:disabled, 1563 | QTimeEdit::down-arrow:off 1564 | { 1565 | background: qlineargradient(x1:0, y1:1, x2:0, y2:0, stop:0 #ffffff, stop:0.6 #eeeeee);/*渐变背景色*/ 1566 | border: 1px solid #dddddd;/*边框*/ 1567 | } 1568 | 1569 | 1570 | /*/////////////////////////////////////////////////QDateEdit///////////////////////////////////////////*/ 1571 | QDateEdit 1572 | { 1573 | min-height:20px; 1574 | padding-right: 15px; 1575 | border: 1px solid #aaaaaa;/*边框*/ 1576 | min-width:10em;/*最小宽度为6em em和px一样为长度单位。em表示对应字体M的宽度。M为大写字母的最大宽度*/ 1577 | } 1578 | 1579 | QDateEdit::up-button 1580 | { 1581 | subcontrol-origin: padding; 1582 | subcontrol-position: top right; /* position at the top right corner */ 1583 | background: qlineargradient(x1:0, y1:0, x2:0, y2:1, stop:0 #ffffff, stop:0.8 #eeeeee);/*渐变背景色*/ 1584 | width: 15px; 1585 | border-left: 1px solid #aaaaaa; 1586 | border-bottom: 0px solid #aaaaaa; 1587 | } 1588 | 1589 | QDateEdit::up-button:hover 1590 | { 1591 | background: qlineargradient(x1:0, y1:0, x2:0, y2:1, stop:0 #eeeeee, stop:0.8 #ffffff);/*渐变背景色*/ 1592 | } 1593 | 1594 | QDateEdit::up-button:pressed 1595 | { 1596 | background: qlineargradient(x1:0, y1:0, x2:0, y2:1, stop:0 #ffffff, stop:0.8 #dddddd);/*渐变背景色*/ 1597 | } 1598 | 1599 | QDateEdit::up-arrow 1600 | { 1601 | image:url(:/qss/icon/ver_scroll_top_arrow.png); 1602 | width: 9px; 1603 | height: 9px; 1604 | } 1605 | 1606 | QDateEdit::up-arrow:disabled, 1607 | QDateEdit::up-arrow:off 1608 | { 1609 | background: qlineargradient(x1:0, y1:0, x2:0, y2:1, stop:0 #ffffff, stop:0.6 #eeeeee);/*渐变背景色*/ 1610 | border: 1px solid #dddddd;/*边框*/ 1611 | } 1612 | 1613 | QDateEdit::down-button 1614 | { 1615 | subcontrol-origin: padding; 1616 | subcontrol-position: bottom right; 1617 | background: qlineargradient(x1:0, y1:1, x2:0, y2:0, stop:0 #ffffff, stop:0.8 #eeeeee);/*渐变背景色*/ 1618 | width: 15px; 1619 | border-left: 1px solid #aaaaaa; 1620 | border-top: 0px solid #aaaaaa; 1621 | } 1622 | 1623 | QDateEdit::down-button:hover 1624 | { 1625 | background: qlineargradient(x1:0, y1:1, x2:0, y2:0, stop:0 #eeeeee, stop:0.8 #ffffff);/*渐变背景色*/ 1626 | } 1627 | 1628 | QTimeEdit::down-button:pressed 1629 | { 1630 | background: qlineargradient(x1:0, y1:1, x2:0, y2:0, stop:0 #ffffff, stop:0.8 #dddddd);/*渐变背景色*/ 1631 | } 1632 | 1633 | QDateEdit::down-arrow 1634 | { 1635 | image:url(:/qss/icon/ver_scroll_bottom_arrow.png); 1636 | width: 9px; 1637 | height: 9px; 1638 | } 1639 | 1640 | QDateEdit::down-arrow:disabled, 1641 | QDateEdit::down-arrow:off 1642 | { 1643 | background: qlineargradient(x1:0, y1:1, x2:0, y2:0, stop:0 #ffffff, stop:0.6 #eeeeee);/*渐变背景色*/ 1644 | border: 1px solid #dddddd;/*边框*/ 1645 | } 1646 | 1647 | /*/////////////////////////////////////////////////QDateTimeEdit///////////////////////////////////////////*/ 1648 | QDateTimeEdit 1649 | { 1650 | min-height:20px; 1651 | padding-right: 15px; 1652 | border: 1px solid #aaaaaa;/*边框*/ 1653 | background:white; 1654 | } 1655 | 1656 | QDateTimeEdit::up-button 1657 | { 1658 | subcontrol-origin: padding; 1659 | subcontrol-position: top right; /* position at the top right corner */ 1660 | background: qlineargradient(x1:0, y1:0, x2:0, y2:1, stop:0 #ffffff, stop:0.8 #eeeeee);/*渐变背景色*/ 1661 | width: 15px; 1662 | border-left: 1px solid #aaaaaa; 1663 | border-bottom: 0px solid #aaaaaa; 1664 | } 1665 | 1666 | QDateTimeEdit::up-button:hover 1667 | { 1668 | background: qlineargradient(x1:0, y1:0, x2:0, y2:1, stop:0 #eeeeee, stop:0.8 #ffffff);/*渐变背景色*/ 1669 | } 1670 | 1671 | QDateTimeEdit::up-button:pressed 1672 | { 1673 | background: qlineargradient(x1:0, y1:0, x2:0, y2:1, stop:0 #ffffff, stop:0.8 #dddddd);/*渐变背景色*/ 1674 | } 1675 | 1676 | QDateTimeEdit::up-arrow 1677 | { 1678 | image:url(:/qss/icon/ver_scroll_top_arrow.png); 1679 | width: 9px; 1680 | height: 9px; 1681 | } 1682 | 1683 | QDateTimeEdit::up-arrow:disabled, 1684 | QDateTimeEdit::up-arrow:off 1685 | { 1686 | background: qlineargradient(x1:0, y1:0, x2:0, y2:1, stop:0 #ffffff, stop:0.6 #eeeeee);/*渐变背景色*/ 1687 | border: 1px solid #dddddd;/*边框*/ 1688 | } 1689 | 1690 | QDateTimeEdit::down-button 1691 | { 1692 | subcontrol-origin: padding; 1693 | subcontrol-position: bottom right; 1694 | background: qlineargradient(x1:0, y1:1, x2:0, y2:0, stop:0 #ffffff, stop:0.8 #eeeeee);/*渐变背景色*/ 1695 | width: 15px; 1696 | border-left: 1px solid #aaaaaa; 1697 | border-top: 0px solid #aaaaaa; 1698 | } 1699 | 1700 | QDateTimeEdit::down-button:hover 1701 | { 1702 | background: qlineargradient(x1:0, y1:1, x2:0, y2:0, stop:0 #eeeeee, stop:0.8 #ffffff);/*渐变背景色*/ 1703 | } 1704 | 1705 | QDateTimeEdit::down-button:pressed 1706 | { 1707 | background: qlineargradient(x1:0, y1:1, x2:0, y2:0, stop:0 #ffffff, stop:0.8 #dddddd);/*渐变背景色*/ 1708 | } 1709 | 1710 | QDateTimeEdit::down-arrow 1711 | { 1712 | image:url(:/qss/icon/ver_scroll_bottom_arrow.png); 1713 | width: 9px; 1714 | height: 9px; 1715 | } 1716 | 1717 | QDateTimeEdit::down-arrow:disabled, 1718 | QDateTimeEdit::down-arrow:off 1719 | { 1720 | background: qlineargradient(x1:0, y1:1, x2:0, y2:0, stop:0 #ffffff, stop:0.6 #eeeeee);/*渐变背景色*/ 1721 | border: 1px solid #dddddd;/*边框*/ 1722 | } 1723 | 1724 | /*/////////////////////////////////////////////////QGraphicsView///////////////////////////////////////////*/ 1725 | QGraphicsView 1726 | { 1727 | border:none; 1728 | } 1729 | /*/////////////////////////////////////////////////QSizeGrip///////////////////////////////////////////*/ 1730 | QSizeGrip 1731 | { 1732 | image: url(:/qss/icon/sizegrip.png); 1733 | width: 15px; 1734 | height: 15px; 1735 | } 1736 | 1737 | /*/////////////////////////////////////////////////QDockWidget///////////////////////////////////////////*/ 1738 | QDockWidget 1739 | { 1740 | border: 1px solid #aaaaaa; 1741 | background: #f2f2f2; 1742 | } 1743 | 1744 | QDockWidget::title { 1745 | text-align: left; /* align the text to the left */ 1746 | background: #f0f0f0; 1747 | padding-left: 5px; 1748 | padding-right: 5px; 1749 | border-bottom:1 solid #aaaaaa; 1750 | } 1751 | 1752 | QMainWindow::separator 1753 | { 1754 | width:0px; 1755 | height:0px; 1756 | border-width: 1px; 1757 | border-color:#f2f2f2 #f2f2f2 #aaaaaa #aaaaaa ; 1758 | border-style:solid; 1759 | } 1760 | 1761 | /*/////////////////////////////////////////////////QLCDNumber///////////////////////////////////////////*/ 1762 | QLCDNumber 1763 | { 1764 | /*background:white;*/ 1765 | } 1766 | -------------------------------------------------------------------------------- /src/include/data/elf/structs.hpp: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include 4 | 5 | struct SELF 6 | { 7 | struct elf64_s 8 | { 9 | Elf64_Ehdr *Header; 10 | Elf64_Phdr *Program; 11 | 12 | } elf64; 13 | 14 | struct elf32_s 15 | { 16 | Elf32_Ehdr *Header; 17 | Elf32_Phdr *Program; 18 | 19 | } elf32; 20 | 21 | int classElf; 22 | }; -------------------------------------------------------------------------------- /src/include/data/erros.hpp: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | /** 4 | * @brief errors that can occur during the passing of the pid 5 | */ 6 | enum ERROR_PID 7 | { 8 | PID_OVERDRIVE = -3, 9 | PID_NOT_READ, 10 | PID_NOT_FOUND, 11 | PID_SUCCESS 12 | }; 13 | 14 | /** 15 | * @brief erros files 16 | */ 17 | enum ERROS_FILES 18 | { 19 | OPEN_SUCCESS, 20 | OPEN_FAIL, 21 | READ_SUCCESS, 22 | READ_FAIL, 23 | WRITE_FAIL, 24 | WRITE_SUCCESS, 25 | EMPTY, 26 | FULL, 27 | }; 28 | 29 | /** 30 | * @brief mem find 31 | * 32 | */ 33 | enum FIND_MEM 34 | { 35 | NOT_FOUND, 36 | FOUND 37 | }; 38 | 39 | 40 | enum STOPP 41 | { 42 | STOPPED, 43 | CONT 44 | }; 45 | 46 | /** 47 | * @brief is enum for verify files 48 | * and valid format ELF 49 | */ 50 | enum 51 | { 52 | ELF_INVALID, 53 | ELF_VALID 54 | }; -------------------------------------------------------------------------------- /src/include/data/map/structs.hpp: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include 4 | #include 5 | 6 | /** 7 | * @brief clean string 8 | * @note using for 'free' string to buffer 9 | */ 10 | #define CLEAR_STRING(__str) __str.clear(); 11 | 12 | /** 13 | * @brief Get pid max your system support 14 | * @note this len file /proc/sys/kernel/pid_max 15 | */ 16 | #define PID_MAX \ 17 | std::string buffer; \ 18 | m_FS.readFS("/proc/sys/kernel/pid_max", buffer, 10); \ 19 | m_infos.pid_max = std::stoi(buffer); \ 20 | CLEAR_STRING(buffer); 21 | 22 | #define MAPS "/maps" 23 | #define BUFFER_READ_UTILS 15 24 | 25 | struct Maps 26 | { 27 | off_t addr_on; 28 | off_t addr_off; 29 | uint64_t size_map; 30 | off_t offset; 31 | std::string flags; 32 | std::string pathname; 33 | }; 34 | 35 | struct Infos 36 | { 37 | pid_t pid; 38 | pid_t pid_max; 39 | 40 | }; 41 | 42 | /** 43 | * @brief get utils info pid 44 | * 45 | */ 46 | enum 47 | { 48 | NAME = 1, 49 | WCHAN, 50 | SESSIONID, 51 | CMDLINE, 52 | LOGINUID, 53 | SIZEBIN, 54 | BLOCKSIZEBIN, 55 | EXEDIR, 56 | COUNT, 57 | }; 58 | 59 | enum 60 | { 61 | HOSTNAME = COUNT, 62 | OSREALESE, 63 | VERSION, 64 | TYPE, 65 | }; -------------------------------------------------------------------------------- /src/include/data/win/structs.hpp: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #define TITLE_WINDOW "maProc" 4 | #define ICON_WINDOW "../src/gui/assets/maProc.png" 5 | #define ICON_PASS_PID "../src/gui/assets/pid_proc.png" 6 | #define ICON_RPASS_PID "../src/gui/assets/rpid.png" 7 | #define ICON_CLEAN "../src/gui/assets/clean.png" 8 | #define ICON_SEARCH "../src/gui/assets/search.png" 9 | #define ICON_CLOSE "../src/gui/assets/close.png" 10 | #define ICON_EDIT "../src/gui/assets/edit.png" 11 | #define ICON_NEW "../src/gui/assets/new.png" 12 | #define ICON_ABOUT "../src/gui/assets/about.png" 13 | #define ICON_HEX "../src/gui/assets/hex.png" 14 | #define ICON_KILL "../src/gui/assets/kill.png" 15 | #define ICON_STOP "../src/gui/assets/stop.png" 16 | #define ICON_PLAY "../src/gui/assets/play.png" 17 | #define ICON_HELP "../src/gui/assets/help.png" 18 | #define ICON_SCREEN "../src/gui/assets/show.png" 19 | #define ICON_SAVE "../src/gui/assets/save.png" 20 | 21 | #define NULL_STR "(null)" 22 | #define CLEAN_ROW "" 23 | 24 | /** 25 | * @brief heap and stack table enumeration 26 | */ 27 | enum 28 | { 29 | Address, 30 | Value, 31 | Memory 32 | }; 33 | 34 | /** 35 | * @brief Infos table enumeration 36 | */ 37 | enum 38 | { 39 | Address_on, 40 | Address_off, 41 | Size_map, 42 | Flags 43 | }; 44 | 45 | enum 46 | { 47 | Address_start, 48 | Address_stop, 49 | Perms, 50 | Offset, 51 | Pathname 52 | }; 53 | 54 | enum 55 | { 56 | e_magic, 57 | e_version, 58 | e_entry, 59 | e_phoff, 60 | e_shoff, 61 | e_abiversion, 62 | e_flags, 63 | e_shentsize, 64 | e_shnum, 65 | e_shstrndx, 66 | e_class, 67 | e_abi, 68 | e_type, 69 | e_machine 70 | }; 71 | 72 | 73 | /** 74 | * @brief pid table enumeration 75 | */ 76 | enum 77 | { 78 | Pid, 79 | Name, 80 | User 81 | }; 82 | -------------------------------------------------------------------------------- /src/include/elf/relf.cpp: -------------------------------------------------------------------------------- 1 | #include "relf.hpp" 2 | #include 3 | #include 4 | #include 5 | #include 6 | #include 7 | #include 8 | #include 9 | #include 10 | 11 | #if __BYTE_ORDER == __LITTLE_ENDIAN 12 | #define ELFDATANATIVE ELFDATA2LSB 13 | #elif __BYTE_ORDER == __BIG_ENDIAN 14 | #define ELFDATANATIVE ELFDATA2MSB 15 | #else 16 | #error "Unknown machine endian" 17 | #endif 18 | 19 | // pointer for 20 | const char *ElfPointer; // pointer for ElfMap 21 | struct SELF Elf; 22 | 23 | static void SwapEndian64 ( ) 24 | { 25 | Elf.elf64.Header->e_type = bswap_16 ( Elf.elf64.Header->e_type ); 26 | Elf.elf64.Header->e_entry = bswap_64 ( Elf.elf64.Header->e_entry ); 27 | Elf.elf64.Header->e_version = bswap_32 ( Elf.elf64.Header->e_version ); 28 | Elf.elf64.Header->e_shstrndx = bswap_16 ( Elf.elf64.Header->e_shstrndx ); 29 | Elf.elf64.Header->e_shnum = bswap_16 ( Elf.elf64.Header->e_shnum ); 30 | Elf.elf64.Header->e_shoff = bswap_64 ( Elf.elf64.Header->e_shoff ); 31 | Elf.elf64.Header->e_phentsize = bswap_16 ( Elf.elf64.Header->e_phentsize ); 32 | Elf.elf64.Header->e_flags = bswap_16 ( Elf.elf64.Header->e_flags ); 33 | Elf.elf64.Header->e_machine = bswap_16 ( Elf.elf64.Header->e_machine ); 34 | Elf.elf64.Header->e_phoff = bswap_64 ( Elf.elf64.Header->e_phoff ); 35 | } 36 | 37 | static void SwapEndian32() 38 | { 39 | Elf.elf32.Header->e_type = bswap_16 ( Elf.elf32.Header->e_type ); 40 | Elf.elf32.Header->e_entry = bswap_32 ( Elf.elf32.Header->e_entry ); 41 | Elf.elf32.Header->e_version = bswap_32 ( Elf.elf32.Header->e_version ); 42 | Elf.elf32.Header->e_shstrndx = bswap_16 ( Elf.elf32.Header->e_shstrndx ); 43 | Elf.elf32.Header->e_shnum = bswap_16 ( Elf.elf32.Header->e_shnum ); 44 | Elf.elf32.Header->e_shoff = bswap_32 ( Elf.elf32.Header->e_shoff ); 45 | Elf.elf32.Header->e_phentsize = bswap_16 ( Elf.elf32.Header->e_phentsize ); 46 | Elf.elf32.Header->e_flags = bswap_16 ( Elf.elf32.Header->e_flags ); 47 | Elf.elf32.Header->e_machine = bswap_16 ( Elf.elf32.Header->e_machine ); 48 | Elf.elf32.Header->e_phoff = bswap_32 ( Elf.elf32.Header->e_phoff ); 49 | } 50 | 51 | 52 | /** 53 | * @brief elf header 54 | * @param [in] p_Elf.elf64.Header struct for usage elf header 55 | * @return void 56 | */ 57 | void ElfStruct ( struct SELF &p_elf ) 58 | { 59 | if ( Elf.elf64.Header->e_ident[EI_CLASS] == ELFCLASS32 ) 60 | { 61 | p_elf.elf32.Header = Elf.elf32.Header; 62 | p_elf.classElf = ELFCLASS32; 63 | 64 | p_elf.elf64.Header = NULL; 65 | p_elf.elf64.Program = NULL; 66 | } 67 | else 68 | { 69 | p_elf.elf64.Header = Elf.elf64.Header; 70 | p_elf.classElf = ELFCLASS64; 71 | 72 | p_elf.elf32.Header = NULL; 73 | p_elf.elf32.Program = NULL; 74 | } 75 | 76 | // verify endian 77 | if ( Elf.elf64.Header->e_ident[EI_DATA] != ELFDATANATIVE ) 78 | { 79 | if ( Elf.elf64.Header->e_ident[EI_CLASS] == ELFCLASS64 ) 80 | SwapEndian64(); 81 | else 82 | SwapEndian32(); 83 | } 84 | } 85 | 86 | /** 87 | * @brief verify format elf for analisy 88 | * @return bool if format elf true, return "true" else false 89 | */ 90 | static bool VElfMagic() 91 | { 92 | return Elf.elf64.Header->e_ident[EI_MAG0] == 0x7f && 93 | Elf.elf64.Header->e_ident[EI_MAG1] == 0x45 && 94 | Elf.elf64.Header->e_ident[EI_MAG2] == 0x4c && 95 | Elf.elf64.Header->e_ident[EI_MAG3] == 0x46; 96 | } 97 | 98 | /** 99 | * @brief map binary in memory to analyze ELF 100 | * @param [in] p_path path name bin ELF for mapper 101 | * @return int if file is found and opened, return OPEN_SUCESS, else OPEN_FAIL 102 | * @details it will just map elf binaries, that is, it will do a check when mapping 103 | the file checking if the file in question is an ELF format 104 | */ 105 | int PElf ( const char *p_path ) 106 | { 107 | int status_exit = OPEN_SUCCESS; 108 | struct stat sb; 109 | 110 | int fd = open ( p_path, O_RDONLY ); 111 | 112 | if ( fd != -1 ) 113 | { 114 | fstat ( fd, &sb ); // get size file for mapping 115 | 116 | // mapper file ELF 117 | ElfPointer = ( char * ) mmap ( nullptr, sb.st_size, PROT_READ | PROT_WRITE, MAP_PRIVATE, fd, 0 ); 118 | 119 | if ( ElfPointer == MAP_FAILED ) 120 | { 121 | perror ( ElfPointer ); 122 | status_exit = ELF_INVALID; 123 | } 124 | else 125 | { 126 | Elf.elf64.Header = ( Elf64_Ehdr * ) ElfPointer; 127 | 128 | if ( Elf.elf64.Header->e_ident[EI_CLASS] == ELFCLASS32 ) 129 | Elf.elf32.Header = ( Elf32_Ehdr * ) Elf.elf64.Header; 130 | if ( VElfMagic() == true ) // elf valid 131 | status_exit = ELF_VALID; 132 | } 133 | 134 | // close file 135 | close ( fd ); 136 | } 137 | else 138 | perror ( p_path ), status_exit = OPEN_FAIL; 139 | 140 | 141 | return status_exit; 142 | } 143 | 144 | 145 | /** 146 | * @brief get pointer e_ident elf 147 | * @return char* 148 | * @details limit EI_NIDENT 149 | */ 150 | unsigned char *ElfMagic() 151 | { 152 | return Elf.elf64.Header->e_ident; 153 | } -------------------------------------------------------------------------------- /src/include/elf/relf.hpp: -------------------------------------------------------------------------------- 1 | /** 2 | * @file relf.h 3 | * @author VitorMob 4 | * @date 13 Mar 2022 5 | * @copyright 2022 VitorMob 6 | * @brief simple parser for analisys binary ELF for student 7 | */ 8 | 9 | #pragma once 10 | 11 | #include 12 | #include 13 | #include 14 | #include 15 | 16 | #include "src/include/data/erros.hpp" 17 | #include "src/include/data/elf/structs.hpp" 18 | 19 | //=================== functions usage for parser elf =================== 20 | int PElf ( const char * ); // pass elf for analisys 21 | void ElfStruct ( struct SELF& ); // get header information elf 22 | unsigned char* ElfMagic(); // return pointer array magic elf 23 | -------------------------------------------------------------------------------- /src/include/fd/filedescriptor.cpp: -------------------------------------------------------------------------------- 1 | #include "filedescriptor.hpp" 2 | #include "src/include/data/map/structs.hpp" 3 | #include "src/include/data/erros.hpp" 4 | 5 | #include 6 | #include 7 | #include 8 | #include 9 | 10 | /** 11 | * @brief Construct a new File Descriptor:: File Descriptor object 12 | * 13 | */ 14 | FileDescriptor::FileDescriptor() 15 | { 16 | } 17 | 18 | /** 19 | * @brief Destroy the File Descriptor:: File Descriptor object 20 | * 21 | */ 22 | FileDescriptor::~FileDescriptor() 23 | { 24 | } 25 | 26 | /** 27 | * @brief this method will read the entire past file 28 | * 29 | * @param p_name name for read file 30 | * @param p_buffer in which variable will you store 31 | * @param p_nblock block size for reading 32 | * @param p_blockm if this option is turned on the block size will multiply by 2 per p_nblock 33 | * 34 | * @return long, if reading file success return READ_SUCCESS else if not len READ_FAIL not open file return OPEN_FAIL 35 | */ 36 | long FileDescriptor::readFS ( std::string p_name, std::string &p_buffer, long p_nblock = 256, bool p_blockm ) 37 | { 38 | 39 | CLEAR_STRING ( p_buffer ) 40 | 41 | long status_exit = READ_SUCCESS; 42 | 43 | off_t nblock = p_nblock; 44 | const char *name = p_name.data(); 45 | 46 | p_buffer.reserve ( p_nblock ); 47 | int FS = open ( name, O_RDONLY ); 48 | 49 | if ( FS > 0 ) 50 | { 51 | do 52 | { 53 | char buffer[nblock]; 54 | memset ( buffer, 0, nblock ); // clean buffer array 55 | 56 | if ( read ( FS, buffer, nblock ) == 0 ) 57 | break; 58 | 59 | p_buffer += buffer; // save block in variable p_buffer 60 | 61 | // increase the bytes of the block thus decreasing the read cycles 62 | // it could possibly end up exceeding the file buffer limit by allocating more than necessary 63 | ( p_blockm ) ? nblock += p_nblock : nblock; 64 | 65 | } while ( FS != EOF ); 66 | 67 | if ( p_buffer.size() == 0 ) 68 | throw std::runtime_error ( "Not possible read file, check permission " + p_name ); 69 | 70 | 71 | close ( FS ); 72 | } 73 | else 74 | throw std::runtime_error ( "Error open file " + p_name ); 75 | 76 | 77 | return status_exit; 78 | } -------------------------------------------------------------------------------- /src/include/fd/filedescriptor.hpp: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | /** 4 | * this file descriptor was created in order to read 'peseudos files' 5 | * from linux as we are parsing /proc/, we created this filedescriptor 6 | * to make it easy to manipulate linux files 7 | */ 8 | 9 | #include 10 | 11 | /** 12 | * @brief class for len pseudos files /proc 13 | * 14 | */ 15 | class FileDescriptor 16 | { 17 | public: 18 | FileDescriptor(); 19 | ~FileDescriptor(); 20 | 21 | long readFS(std::string , std::string &, long , bool = false); 22 | }; -------------------------------------------------------------------------------- /src/include/map/pmap.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | #include 6 | #include 7 | #include 8 | #include 9 | #include 10 | 11 | #include "pmap.hpp" 12 | #include "src/include/data/erros.hpp" 13 | 14 | /** 15 | * @brief function verify pid for passed in user 16 | * @param p_pid pass pid for verification is exist 17 | * @param p_max pass to max pid for verification for not ultrapassing pid limit 18 | * @return int 19 | * 20 | * if process exist for linux return true else false 21 | */ 22 | static void verify_pid(pid_t p_pid, pid_t p_max) 23 | { 24 | if (p_pid <= 0 || p_pid > p_max) 25 | throw std::runtime_error("Pid " + std::to_string(p_pid) + " passed is not valid, valid pid not less 0 or larger " + std::to_string(p_max)); 26 | else 27 | { 28 | std::string proc = PROC + std::to_string(p_pid); 29 | DIR *dir = opendir(proc.c_str()); 30 | 31 | if (dir == nullptr) 32 | throw std::runtime_error("Pid not found, verify to pid and pass pid valid"); 33 | else 34 | closedir(dir); 35 | } 36 | } 37 | 38 | void Pmap::split_maps() 39 | { 40 | std::string line; 41 | for (int i = 0; i <= m_maps_buf.size(); i++) 42 | { 43 | line += m_maps_buf.substr(i, 1); 44 | if (m_maps_buf.data()[i] == '\n') 45 | { 46 | split_mem_address(line); 47 | m_maps_buf.erase(0, i); 48 | i = 0; 49 | } 50 | } 51 | } 52 | 53 | /** 54 | * @brief will do a get the addresses from the line 55 | * @param __line which line to pass to get the addresses 56 | * 57 | * Big O(n²) 58 | * @return void 59 | */ 60 | void Pmap::split_mem_address(std::string &p_foo) 61 | { 62 | std::string addr_on; 63 | std::string addr_off; 64 | std::string offset; 65 | 66 | std::size_t size = p_foo.size(); 67 | 68 | for (std::size_t i = 0; i <= size; i++) 69 | { 70 | if (p_foo[i] == '-') 71 | { 72 | for (std::size_t j = i + 1; j <= size; j++) 73 | { 74 | addr_off += p_foo[j]; 75 | 76 | if (p_foo[j] == ' ') 77 | { 78 | for (std::size_t k = j + 1; k <= size; k++) 79 | { 80 | m_maps.flags += p_foo[k]; 81 | 82 | if (p_foo[k] == ' ') 83 | { 84 | for (std::size_t m = k + 1; m <= size; m++) 85 | { 86 | offset += p_foo[m]; 87 | if (p_foo[m] == ' ') 88 | break; 89 | } 90 | break; 91 | } 92 | } 93 | break; 94 | } 95 | } 96 | break; 97 | } 98 | addr_on += p_foo[i]; 99 | } 100 | 101 | for (std::size_t l = m_maps.flags.size() + addr_off.size() + addr_on.size() + 25; l <= size; l++) 102 | { 103 | m_maps.pathname += p_foo[l]; 104 | if (p_foo[l] == '\n') 105 | break; 106 | } 107 | 108 | if (addr_on.size() == 0 || addr_off.size() == 0) 109 | throw std::runtime_error("Error not split address_on and address_off"); 110 | 111 | // convert string to off_t 112 | m_maps.addr_on = (off_t)std::stoul(addr_on, nullptr, 16); 113 | m_maps.addr_off = (off_t)std::stoul(addr_off, nullptr, 16); 114 | m_maps.offset = (off_t)std::stoul(offset, nullptr, 16); 115 | m_maps.pathname.erase(remove_if(m_maps.pathname.begin(), m_maps.pathname.end(), isspace), m_maps.pathname.end()); 116 | 117 | m_unmap.insert(std::make_pair(m_maps.pathname, m_maps)); 118 | 119 | CLEAR_STRING(p_foo); 120 | CLEAR_STRING(m_maps.flags); 121 | CLEAR_STRING(addr_off); 122 | CLEAR_STRING(addr_on); 123 | CLEAR_STRING(m_maps.pathname); 124 | CLEAR_STRING(offset); 125 | } 126 | 127 | /** 128 | * @brief Constructor 129 | */ 130 | Pmap::Pmap() 131 | { 132 | m_infos.pid_max = 0; 133 | m_infos.pid = 0; 134 | m_maps.addr_on = 0; 135 | m_maps.addr_off = 0; 136 | PID_MAX 137 | } 138 | 139 | /** 140 | * @brief Destructor 141 | */ 142 | Pmap::~Pmap() 143 | { 144 | CLEAR_STRING(m_maps_buf); 145 | } 146 | 147 | /** 148 | * @brief Mapper process passing pid 149 | * @param p_pid pid of the process to be mapped 150 | * @return int 151 | * 152 | * pid not found return PID_NOT_FOUND 153 | * if the pid exists ira return PID_SUCCESS 154 | */ 155 | int Pmap::map_pid(pid_t p_pid) 156 | { 157 | m_infos.pid = p_pid; 158 | 159 | verify_pid(m_infos.pid, m_infos.pid_max); 160 | RemoteProcess::openProcess(m_infos.pid); 161 | 162 | m_FS.readFS(PROC + std::to_string(m_infos.pid) + MAPS, m_maps_buf, 2048, true); 163 | 164 | if (m_maps_buf.size() == 0) 165 | throw std::runtime_error("Looks like proc/" + std::to_string(m_infos.pid) + "/maps is empty, I do a check in the past process"); 166 | else 167 | { 168 | m_unmap.clear(); 169 | split_maps(); 170 | } 171 | return PID_SUCCESS; 172 | } 173 | 174 | /** 175 | * @brief verify mem if process usage 176 | * @param p_mem memory to be mapped will check if it exists and map such memory 177 | * @return bool 178 | * 179 | * if the use of memory is `not` being used it returns true or returns false 180 | * if the memory is not being used by the process, it will map right away 181 | * that the memory is being used 182 | */ 183 | bool Pmap::map_mem(const std::string &p_mem) 184 | { 185 | bool status_exit = false; 186 | 187 | if (m_unmap[p_mem].addr_on != 0) 188 | { 189 | m_maps.flags = m_unmap[p_mem].flags; 190 | m_maps.addr_on = m_unmap[p_mem].addr_on; 191 | m_maps.addr_off = m_unmap[p_mem].addr_off; 192 | m_maps.size_map = m_maps.addr_off - m_maps.addr_on; 193 | m_maps.pathname = m_unmap[p_mem].pathname; 194 | 195 | status_exit = true; 196 | } 197 | else 198 | throw std::runtime_error("Process not using memory " + p_mem); 199 | 200 | return status_exit; 201 | } 202 | 203 | /** 204 | * @brief Mem write passing address for to modify 205 | * @param p_addr pass address for modify 206 | * @param __val pass value for modify 207 | * @return bool 208 | */ 209 | bool Pmap::map_write(off_t p_addr, void *__value, uint p_size) 210 | { 211 | bool status_exit = false; 212 | 213 | Data data((uint8_t *)__value, p_size); 214 | 215 | if (RemoteProcess::writeMem(p_addr, &data) != WRITE_FAIL) 216 | status_exit = true; 217 | 218 | return status_exit; 219 | } 220 | 221 | /** 222 | * @brief Reading mem for address in process to preference heap or stack 223 | * @param __on address for init reading memory 224 | * @param __off for end address mapped 225 | * @return bool 226 | */ 227 | bool Pmap::map_read(off_t p_addr, uint p_size, Data &p_data) 228 | { 229 | bool status_exit = false; 230 | 231 | if (RemoteProcess::readMem(p_addr, p_addr + p_size, &p_data) != READ_FAIL) 232 | status_exit = true; 233 | 234 | return status_exit; 235 | } 236 | 237 | /** 238 | * @brief will scan the memory looking for the 239 | * desired values ​​and the specific type 240 | * 241 | * @param p_addr start address for find 242 | * @param p_length size memory for read and find 243 | * @param p_find value for find 244 | * @param p_type type for search 245 | * @param p_offsets store the found offsets in a vector 246 | * @return int 247 | */ 248 | int Pmap::map_find(off_t p_addr, uint64_t p_length, std::string p_find, uint8_t p_type, std::vector &p_offsets) 249 | { 250 | if (!isdigit(p_find[0]) && 251 | p_type == sizeof(char) && 252 | p_find.size() == 1) 253 | { 254 | goto analyze; 255 | 256 | } 257 | else if (p_type == sizeof(int) || 258 | p_type == sizeof(uint16_t) || 259 | p_type == sizeof(int64_t)) 260 | { 261 | if (isdigit(p_find[0])) 262 | goto analyze; 263 | else 264 | goto error; 265 | } 266 | else if (p_type == sizeof(std::string)) 267 | goto analyze; 268 | 269 | else 270 | goto error; 271 | 272 | analyze: 273 | return RemoteProcess::findMem(p_addr, p_length, p_type, p_find, p_offsets); 274 | 275 | error: 276 | throw std::runtime_error("Error, character '" + p_find + "' not valid"); 277 | } 278 | 279 | /** 280 | * @brief stop process if process stopped continue 281 | * 282 | */ 283 | void Pmap::map_stop(bool p_enable) 284 | { 285 | if (m_infos.pid != 0) 286 | RemoteProcess::stopPid(p_enable); 287 | } 288 | 289 | /** 290 | * @brief kill process 291 | * 292 | */ 293 | void Pmap::map_kill() 294 | { 295 | if (m_infos.pid != 0) 296 | RemoteProcess::killPid(); 297 | } 298 | 299 | /** 300 | * @brief take the pid utility as an example, the name of the pid, 301 | * just pass it as a NAME parameter, which will return the process name 302 | * 303 | * @param p_utils parameter used to get the pid information 304 | * @return std::string 305 | */ 306 | std::string Pmap::get_utilsPid(uint8_t p_utils) 307 | { 308 | std::string buffer; 309 | struct stat stats; 310 | std::string pid_str = std::to_string(m_infos.pid); 311 | std::string name = PROC + pid_str; 312 | 313 | if (m_infos.pid != 0) 314 | { 315 | switch (p_utils) 316 | { 317 | case NAME: 318 | name += "/comm"; 319 | m_FS.readFS(name, buffer, BUFFER_READ_UTILS); 320 | break; 321 | 322 | case WCHAN: 323 | name += "/wchan"; 324 | m_FS.readFS(name, buffer, BUFFER_READ_UTILS); 325 | break; 326 | 327 | case SESSIONID: 328 | name += "/sessionid"; 329 | m_FS.readFS(name, buffer, BUFFER_READ_UTILS); 330 | break; 331 | 332 | case CMDLINE: 333 | name += "/cmdline"; 334 | m_FS.readFS(name, buffer, BUFFER_READ_UTILS); 335 | break; 336 | 337 | case LOGINUID: 338 | name += "/loginuid"; 339 | m_FS.readFS(name, buffer, BUFFER_READ_UTILS); 340 | break; 341 | 342 | case SIZEBIN: 343 | name += "/exe"; 344 | 345 | if (stat(name.data(), &stats) == 0) 346 | buffer = std::to_string(stats.st_size); 347 | 348 | break; 349 | 350 | case BLOCKSIZEBIN: 351 | name += "/exe"; 352 | 353 | if (stat(name.data(), &stats) == 0) 354 | buffer = std::to_string(stats.st_blksize); 355 | 356 | break; 357 | 358 | case EXEDIR: 359 | buffer = name += "/exe"; 360 | break; 361 | 362 | default: 363 | throw std::runtime_error("It was not possible to make the get at this value " + std::to_string(p_utils)); 364 | } 365 | } 366 | 367 | if (buffer.size() == 0) 368 | { 369 | switch (p_utils) 370 | { 371 | case HOSTNAME: 372 | m_FS.readFS("/proc/sys/kernel/hostname", buffer, BUFFER_READ_UTILS); 373 | break; 374 | 375 | case OSREALESE: 376 | m_FS.readFS("/proc/sys/kernel/osrelease", buffer, BUFFER_READ_UTILS); 377 | break; 378 | 379 | case VERSION: 380 | m_FS.readFS("/proc/sys/kernel/version", buffer, BUFFER_READ_UTILS); 381 | break; 382 | 383 | case TYPE: 384 | m_FS.readFS("/proc/sys/kernel/ostype", buffer, BUFFER_READ_UTILS); 385 | break; 386 | 387 | default: 388 | throw std::runtime_error("It was not possible to make the get at this value " + std::to_string(p_utils)); 389 | } 390 | } 391 | 392 | return buffer; 393 | } 394 | 395 | const std::unordered_map &Pmap::get_Maps() const 396 | { 397 | return m_unmap; 398 | } 399 | 400 | /** 401 | * @brief get address on 402 | * @return off_t 403 | * 404 | * in address start for mem process 405 | */ 406 | off_t Pmap::get_addrOn() const 407 | { 408 | return m_maps.addr_on; 409 | } 410 | 411 | /** 412 | * @brief get address off 413 | * @return off_t 414 | * 415 | * in address stop for mem process 416 | */ 417 | off_t Pmap::get_addrOff() const 418 | { 419 | return m_maps.addr_off; 420 | } 421 | 422 | /** 423 | * @brief flags in address memory, r(read) w(write) ... 424 | * 425 | * @return std::string 426 | */ 427 | std::string Pmap::get_Flags() 428 | { 429 | return m_maps.flags; 430 | } 431 | 432 | /** 433 | * @brief get address size mapped 434 | * @return uint64_t 435 | */ 436 | uint64_t Pmap::get_sizeAddress() 437 | { 438 | return m_maps.size_map; 439 | } -------------------------------------------------------------------------------- /src/include/map/pmap.hpp: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include 4 | #include 5 | 6 | #include "proclib.hpp" 7 | #include "src/include/data/map/structs.hpp" 8 | #include "src/include/fd/filedescriptor.hpp" 9 | 10 | 11 | /** 12 | * @brief manipulation of process 13 | * 14 | */ 15 | class Pmap : protected RemoteProcess 16 | { 17 | public: 18 | Pmap(); 19 | ~Pmap(); 20 | 21 | int map_pid(pid_t ); 22 | bool map_mem(const std::string &); 23 | 24 | bool map_write(off_t, void *, uint); 25 | bool map_read(off_t, uint, Data &); 26 | int map_find(off_t, uint64_t, std::string, uint8_t, std::vector &); 27 | void map_stop(bool = true); 28 | void map_kill(); 29 | 30 | off_t get_addrOn() const; 31 | off_t get_addrOff() const; 32 | uint64_t get_sizeAddress(); 33 | std::string get_Flags(); 34 | 35 | const std::unordered_map& get_Maps() const; 36 | std::string get_utilsPid(uint8_t); 37 | 38 | private: 39 | Maps m_maps; 40 | Infos m_infos; 41 | FileDescriptor m_FS; 42 | std::string m_maps_buf; 43 | 44 | void split_mem_address(std::string &); 45 | void split_maps(); 46 | 47 | std::unordered_map m_unmap; 48 | }; -------------------------------------------------------------------------------- /src/include/map/proclib.cpp: -------------------------------------------------------------------------------- 1 | #include "proclib.hpp" 2 | #include "src/include/fd/filedescriptor.hpp" 3 | #include "src/include/memory/arena.hpp" 4 | 5 | #include 6 | #include 7 | #include 8 | #include 9 | #include 10 | #include 11 | #include 12 | 13 | Arena fast(ARENA_BUFFER); 14 | 15 | /** 16 | * @brief routine to analyze memory, 17 | * with the appropriate p_types char, int, int16, int64,'string'I 18 | * 19 | * @param p_buffer memory for analysis 20 | * @param p_find what to look for 21 | * @param p_offsets where to p_start for counting 22 | * @param p_type p_type char, int64 ... 23 | * @return int 24 | */ 25 | void RemoteProcess::analyseMemory(char *p_buffer, std::string p_find, off_t p_offsets, uint8_t p_type, 26 | uint64_t p_lenght, std::vector &p_save) 27 | { 28 | switch (p_type) 29 | { 30 | case sizeof(char): 31 | p_save.clear(); 32 | for (uint64_t i = 0; i < p_lenght; i++) 33 | { 34 | if (p_buffer[i] == p_find[0]) 35 | p_save.push_back(p_offsets); 36 | p_offsets++; 37 | } 38 | break; 39 | case sizeof(int): 40 | p_save.clear(); 41 | { 42 | int p_findP = std::stoi(p_find); 43 | if (p_findP < INT_MAX && p_findP > 0) 44 | { 45 | for (uint64_t i = 0; i < p_lenght; i++) 46 | { 47 | if ((int)p_buffer[i] == p_findP) 48 | p_save.push_back(p_offsets); 49 | p_offsets++; 50 | } 51 | } 52 | } 53 | break; 54 | case sizeof(uint16_t): 55 | p_save.clear(); 56 | { 57 | int16_t p_findP = (uint16_t)std::stoi(p_find); 58 | if (p_findP <= UINT16_MAX && p_findP > 0) 59 | { 60 | for (uint64_t i = 0; i < p_lenght; i++) 61 | { 62 | if ((uint16_t)p_buffer[i] == p_findP) 63 | p_save.push_back(p_offsets); 64 | p_offsets++; 65 | } 66 | } 67 | } 68 | break; 69 | case sizeof(uint64_t): 70 | p_save.clear(); 71 | { 72 | int64_t p_findP = (uint64_t)std::stoi(p_find); 73 | if (p_findP < UINT64_MAX && p_findP > 0) 74 | { 75 | for (uint64_t i = 0; i < p_lenght; i++) 76 | { 77 | if ((int64_t)p_buffer[i] == p_findP) 78 | p_save.push_back(p_offsets); 79 | p_offsets++; 80 | } 81 | } 82 | } 83 | break; 84 | case sizeof(std::string): 85 | p_save.clear(); 86 | { 87 | std::string str; 88 | for (uint64_t it = 0; it < p_lenght; it++) 89 | { 90 | if (p_buffer[it] == p_find[0]) 91 | { 92 | for (std::size_t i = 0; i < p_find.size(); i++) 93 | str += p_buffer[it + i]; 94 | 95 | if (str == p_find) 96 | p_save.push_back(p_offsets); 97 | } 98 | p_offsets++; 99 | } 100 | } 101 | break; 102 | default: 103 | break; 104 | } 105 | } 106 | 107 | RemoteProcess::RemoteProcess() 108 | { 109 | m_status = 0; 110 | } 111 | 112 | /** 113 | * @brief Attach to a remote process 114 | * @param pid_t p_pid to be attached inside the system 115 | * @return int 116 | * 117 | */ 118 | int RemoteProcess::openProcess(pid_t p_pid) 119 | { 120 | m_proc.pid = p_pid; 121 | m_status = OPEN_SUCCESS; 122 | struct stat st; 123 | m_proc.dirmem = PROC + std::to_string(m_proc.pid) + "/mem"; 124 | 125 | if (stat("/proc/self/mem", &st) == 0) 126 | { 127 | m_proc.fd = open(m_proc.dirmem.data(), O_RDWR); 128 | if (m_proc.fd == -1) 129 | m_status = OPEN_FAIL; 130 | } 131 | else 132 | m_status = OPEN_FAIL; 133 | 134 | return m_status; 135 | } 136 | 137 | /** 138 | * @brief Destroy the Remote Process:: Remote Process object 139 | * 140 | */ 141 | RemoteProcess::~RemoteProcess() 142 | { 143 | close(m_proc.fd); 144 | } 145 | 146 | /** 147 | * @brief read memory using pread 148 | * 149 | * @param p_start start offset for read mem 150 | * @param p_stop offset for stop read start + size 151 | * @param p_data where will the reading be stored in memory 152 | * @return int if read sucess return READ_SUCCESS else READ_FAIL 153 | */ 154 | int RemoteProcess::readMem(off_t p_start, off_t p_stop, Data *p_data) 155 | { 156 | if (m_status == OPEN_FAIL) 157 | return READ_FAIL; 158 | 159 | size_t bsize = p_stop - p_start; 160 | if(pread(m_proc.fd, p_data->m_buff, bsize, p_start) == -1) 161 | return READ_FAIL; 162 | 163 | return READ_SUCCESS; 164 | } 165 | 166 | /** 167 | * @brief Write into a remote process memory 168 | * 169 | * @param p_start p_offsets to be written into 170 | * @param p_data class with the target data to be write 171 | * @return int 172 | * 173 | * If the remote memory cannot be written, it will returns WRITE_FAIL, otherwise WRITE_SUCESS. The error cause can be found at the 174 | * errno variable, which is set by ptrace. 175 | */ 176 | int RemoteProcess::writeMem(off_t p_start, Data *p_data) 177 | { 178 | if (m_status == OPEN_FAIL) 179 | return WRITE_FAIL; 180 | 181 | ssize_t write = pwrite(m_proc.fd, reinterpret_cast(p_data->m_buff), p_data->m_size, p_start); 182 | if (write == -1) 183 | return WRITE_FAIL; 184 | 185 | return WRITE_SUCCESS; 186 | } 187 | 188 | /** 189 | * @brief find values ​​in memory 190 | * 191 | * @param p_start offset for start 192 | * @param p_length size for stop read 193 | * @param p_type type for search value 194 | * @param p_find what find 195 | * @param p_offsets store the offsets 196 | * @return int 197 | */ 198 | int RemoteProcess::findMem(off_t p_start, uint64_t p_length, uint8_t p_type, std::string p_find, std::vector &p_offsets) 199 | { 200 | if (m_status == OPEN_FAIL) 201 | { 202 | throw std::runtime_error("Error not open file " + m_proc.dirmem); 203 | return OPEN_FAIL; 204 | } 205 | else if (!m_hasProcMem) 206 | { 207 | try 208 | { 209 | char *p_buffer = (char*)fast.req(p_length); 210 | if (pread(m_proc.fd, p_buffer, p_length, p_start) == -1) 211 | return READ_FAIL; 212 | else 213 | analyseMemory(p_buffer, p_find, p_start, p_type, p_length, p_offsets); 214 | } 215 | catch (std::exception &error) 216 | { 217 | throw std::runtime_error(error.what()); 218 | } 219 | } 220 | else 221 | throw std::runtime_error("Not supported p_find memory, directory 'proc/" + std::to_string(m_proc.pid) + "/mem' not found, \n maProc not support for read mem with ptrace"); 222 | 223 | return READ_SUCCESS; 224 | } 225 | 226 | /** 227 | * @brief stop process 228 | * 229 | * @param p_enable if stopped is return cont set true parameter 230 | */ 231 | void RemoteProcess::stopPid(bool p_enable) 232 | { 233 | if (p_enable == true && m_proc.pid != 0) 234 | kill(m_proc.pid, SIGSTOP); 235 | else 236 | kill(m_proc.pid, SIGCONT); 237 | } 238 | 239 | /** 240 | * @brief kill process 241 | * 242 | */ 243 | void RemoteProcess::killPid() 244 | { 245 | kill(m_proc.pid, SIGKILL); 246 | } 247 | 248 | // 249 | // part of the code in which we are going 250 | // to move the p_buffer for writing to memory and reading 251 | // 252 | 253 | Data::Data(uint p_size) 254 | { 255 | m_size = p_size; 256 | m_buff = new uint8_t[m_size]; 257 | externalRef = false; 258 | m_curr = 0; 259 | } 260 | 261 | Data::Data(uint8_t *p_buff, uint p_size) 262 | { 263 | externalRef = true; 264 | m_buff = p_buff; 265 | m_size = p_size; 266 | m_curr = 0; 267 | } 268 | 269 | Data::~Data() 270 | { 271 | if (!externalRef) 272 | delete[] m_buff; 273 | } 274 | 275 | void Data::write(uint8_t p_b) 276 | { 277 | if (m_curr++ == m_size) 278 | return; 279 | 280 | m_buff[m_curr] = p_b; 281 | } 282 | 283 | uint8_t *Data::read() 284 | { 285 | return (uint8_t *)m_buff; 286 | } 287 | 288 | void Data::clear() 289 | { 290 | memset(m_buff, 0, m_size); 291 | } -------------------------------------------------------------------------------- /src/include/map/proclib.hpp: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include 4 | #include 5 | #include 6 | #include 7 | #include 8 | #include 9 | #include 10 | #include 11 | 12 | #include "src/include/data/erros.hpp" 13 | 14 | #define PROC "/proc/" 15 | #define ARENA_BUFFER 2048 16 | 17 | class Data 18 | { 19 | public: 20 | Data(uint = sysconf ( _SC_PAGESIZE )); 21 | Data(uint8_t *, uint); 22 | virtual ~Data(); 23 | void write(uint8_t); 24 | uint8_t *read(); 25 | void clear(); 26 | uint m_size; 27 | uint8_t *m_buff; 28 | 29 | private: 30 | bool externalRef; 31 | uint m_curr; 32 | }; 33 | 34 | class RemoteProcess 35 | { 36 | protected: 37 | struct Process 38 | { 39 | pid_t pid; 40 | std::string dirmem; 41 | int fd; 42 | 43 | } m_proc; 44 | 45 | RemoteProcess(); 46 | virtual ~RemoteProcess(); 47 | 48 | void analyseMemory(char *, std::string, off_t, 49 | uint8_t, uint64_t, std::vector &); 50 | int openProcess(pid_t); 51 | int readMem(off_t, off_t, Data *); 52 | int writeMem(off_t, Data *); 53 | int findMem(off_t, uint64_t, uint8_t, std::string, std::vector &); 54 | void stopPid(bool); 55 | void killPid(); 56 | 57 | private: 58 | int m_status; 59 | bool m_hasProcMem; 60 | }; 61 | -------------------------------------------------------------------------------- /src/include/memory/arena.cpp: -------------------------------------------------------------------------------- 1 | #include "src/include/memory/arena.hpp" 2 | #include 3 | 4 | /** 5 | * if p_overwrite = true (default) Arena overwrite spaces alocated 6 | * 7 | * */ 8 | Arena::Arena(unsigned int p_size, unsigned int p_limit, bool p_overwrite) : m_size(p_size), 9 | m_amount(m_size), 10 | m_limit(p_limit), 11 | m_overwrite(p_overwrite) 12 | { 13 | m_mem = new char[m_size]; 14 | m_head = m_mem; 15 | } 16 | 17 | Arena::Arena() : m_mem(nullptr), 18 | m_size(0), 19 | m_amount(0), 20 | m_limit(0), 21 | m_head(nullptr), 22 | m_overwrite(0) 23 | { 24 | } 25 | 26 | /* 27 | * avoid copy arena, greater than the heap, but it loses performance 28 | * */ 29 | Arena Arena::operator=(const Arena &fast) 30 | { 31 | delete[] m_mem; 32 | 33 | m_mem = new char[fast.m_size]; 34 | memcpy(m_mem, fast.m_mem, fast.m_size); 35 | m_size = fast.m_size; 36 | m_head = fast.m_head; 37 | m_amount = fast.m_amount; 38 | m_overwrite = fast.m_overwrite; 39 | m_limit = m_amount; 40 | 41 | return *this; 42 | } 43 | 44 | /* 45 | * avoid copy arena, greater than the heap, but it loses performance 46 | */ 47 | Arena::Arena(const Arena &fast) 48 | { 49 | m_mem = new char[fast.m_size]; 50 | memcpy(m_mem, fast.m_mem, fast.m_size); 51 | m_size = fast.m_size; 52 | m_head = fast.m_head; 53 | m_amount = fast.m_amount; 54 | m_overwrite = fast.m_overwrite; 55 | m_limit = m_amount; 56 | } 57 | 58 | Arena::~Arena() 59 | { 60 | delete[] m_mem; 61 | m_mem = nullptr; 62 | m_head = m_mem; 63 | } 64 | 65 | /* 66 | * requestes block in arena passing desired size 67 | * */ 68 | void *Arena::req(unsigned int p_amount) 69 | { 70 | if (p_amount <= m_amount) 71 | { 72 | if (p_amount < m_limit && m_overwrite && m_size > m_limit) 73 | { 74 | realloc(m_limit); 75 | goto new_block; 76 | } 77 | else 78 | goto new_block; 79 | } 80 | else if (p_amount > m_size) 81 | { 82 | realloc(p_amount); 83 | goto new_block; 84 | } 85 | else 86 | { 87 | if (m_overwrite) 88 | { 89 | dell(); 90 | goto new_block; 91 | } 92 | else 93 | throw std::runtime_error("Arena : Arena is full"); 94 | } 95 | 96 | new_block: 97 | char *block = const_cast(m_head); 98 | m_head += p_amount; 99 | m_amount -= p_amount; 100 | 101 | return block; 102 | } 103 | 104 | /* (m_head) 105 | * ↓ 106 | * (m_mem) -> [ ][ ][ ][ ] ... 107 | * return pointer head for initial memory 108 | * */ 109 | void Arena::dell() 110 | { 111 | m_head = m_mem; 112 | m_amount = m_size; 113 | } 114 | 115 | /* 116 | * Delete memory 117 | * */ 118 | void Arena::erase() 119 | { 120 | delete[] m_mem; 121 | m_mem = nullptr; 122 | m_head = m_mem; 123 | m_size = 0; 124 | m_amount = m_size; 125 | m_overwrite = true; 126 | } 127 | 128 | /* 129 | * return amount free space in arena 130 | * */ 131 | unsigned int Arena::fquantity() 132 | { 133 | return m_amount; 134 | } 135 | 136 | /* 137 | * ... [ ][ ][ ] <- [delete] - [alocate more] -> [ ][ ][ ][ ] +++ 138 | * */ 139 | void Arena::realloc(unsigned int p_amount) 140 | { 141 | if (m_mem != nullptr) 142 | delete[] m_mem; 143 | else if(p_amount == 0 || p_amount == m_size) 144 | return; 145 | 146 | m_mem = new char[p_amount]; 147 | m_head = m_mem; 148 | m_size = p_amount; 149 | m_amount = m_size; 150 | } -------------------------------------------------------------------------------- /src/include/memory/arena.hpp: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include 4 | #include 5 | 6 | struct Arena 7 | { 8 | private: 9 | char *m_mem; 10 | unsigned int m_size; 11 | unsigned int m_amount; 12 | unsigned int m_limit; 13 | const char *m_head; 14 | bool m_overwrite; 15 | 16 | public: 17 | ~Arena(); 18 | explicit Arena ( unsigned int , unsigned int p_limit = sysconf ( _SC_PAGESIZE ), bool = true ); 19 | Arena ( const Arena &fast ); 20 | explicit Arena(); 21 | Arena operator= ( const Arena &fast ); 22 | 23 | void realloc ( unsigned int ); 24 | void *req ( unsigned int ); 25 | void dell(); 26 | void erase(); 27 | void remove ( void *p_mem ); 28 | unsigned int fquantity(); 29 | }; -------------------------------------------------------------------------------- /src/include/ps/ps.cpp: -------------------------------------------------------------------------------- 1 | #include "ps.hpp" 2 | 3 | #include 4 | #include 5 | #include 6 | 7 | /** 8 | * @brief Construct a new Ps:: Ps object 9 | * 10 | */ 11 | Ps::Ps() 12 | { 13 | } 14 | 15 | /** 16 | * @brief Destroy the Ps:: Ps object 17 | * 18 | */ 19 | Ps::~Ps() 20 | { 21 | } 22 | 23 | /** 24 | * @brief will get all processes from the magic folder / proc 25 | * will store in the parameters the name and pid equivalent to the process 26 | * 27 | * @param NameProcess pass an array as a parameter to store process names 28 | * @param PidProcess pass an array as a parameter to store process pids 29 | * 30 | */ 31 | void Ps::Reading_DirProcess(std::unordered_map &p_umap) 32 | { 33 | infos infos_pid; 34 | p_umap.clear(); 35 | 36 | DIR *dir = opendir("/proc/"); 37 | struct dirent *dir_read; 38 | 39 | if (dir == nullptr) 40 | { 41 | throw std::runtime_error("Error not open dir /proc"); 42 | } 43 | 44 | while ((dir_read = readdir(dir)) != nullptr) 45 | { 46 | std::string file; 47 | if (strcmp(dir_read->d_name, "self") && strcmp(dir_read->d_name, "thread-self")) 48 | { 49 | try 50 | { 51 | file = "/proc/" + std::string(dir_read->d_name) + "/comm"; 52 | readFS(file, infos_pid.name, 20); 53 | file = "/proc/" + std::string(dir_read->d_name) + "/loginuid"; 54 | readFS(file, infos_pid.user, 20); 55 | infos_pid.pid = dir_read->d_name; 56 | 57 | p_umap.insert(std::make_pair(infos_pid.name, infos_pid)); 58 | } 59 | catch (std::exception &error) 60 | { 61 | file.clear(); 62 | } 63 | } 64 | } 65 | 66 | closedir(dir); 67 | } 68 | -------------------------------------------------------------------------------- /src/include/ps/ps.hpp: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include 4 | #include 5 | 6 | #include "src/include/data/erros.hpp" 7 | #include "src/include/fd/filedescriptor.hpp" 8 | 9 | struct infos 10 | { 11 | std::string pid; 12 | std::string name; 13 | std::string user; 14 | 15 | }; 16 | 17 | class Ps : public FileDescriptor 18 | { 19 | 20 | public: 21 | Ps(); 22 | virtual ~Ps(); 23 | 24 | void Reading_DirProcess ( std::unordered_map &umap ); 25 | }; 26 | -------------------------------------------------------------------------------- /src/main.cpp: -------------------------------------------------------------------------------- 1 | #include "mainwindow.hpp" 2 | #include 3 | 4 | int main(int p_argc, char *p_argv[]) 5 | { 6 | QApplication::setSetuidAllowed(true); 7 | QApplication a(p_argc, p_argv); 8 | 9 | MainWindow w; 10 | w.show(); 11 | 12 | return a.exec(); 13 | } 14 | -------------------------------------------------------------------------------- /src/mainwindow.cpp: -------------------------------------------------------------------------------- 1 | #include "mainwindow.hpp" 2 | #include "dirwindow.hpp" 3 | #include "include/data/win/structs.hpp" 4 | #include "gui/ui_mainwindow.h" 5 | #include "gui/ui_about.h" 6 | #include "include/elf/relf.hpp" 7 | 8 | #include 9 | #include 10 | #include 11 | #include 12 | #include 13 | #include 14 | #include 15 | #include 16 | #include 17 | 18 | // ======================================================================= 19 | // Macros utilizade for mapper determinate memory 20 | // 21 | // ======================================================================= 22 | #define mapper_heap m_mapper.map_mem("[heap]") 23 | #define mapper_stack m_mapper.map_mem("[stack]") 24 | 25 | // ======================================================================= 26 | // Utils macros for dell row 27 | // column, two macro for write log 28 | // 29 | // ======================================================================= 30 | #define column_delete(p_column) \ 31 | { \ 32 | m_ui->progressFind->setValue(0); \ 33 | while (p_column->rowCount() > 0) \ 34 | p_column->removeRow(0); \ 35 | } 36 | 37 | #define write_log(p_string) \ 38 | if (m_ui->checkLog->isChecked()) \ 39 | { \ 40 | time_t now = time(0); \ 41 | char *date_time = ctime(&now); \ 42 | m_ui->log_text->appendPlainText("DATE: " + QString(date_time) + p_string); \ 43 | } 44 | 45 | // ======================================================================= 46 | // Constructor and Destructor 47 | // 48 | // ======================================================================= 49 | MainWindow::MainWindow(QWidget *p_parent) : QMainWindow(p_parent), 50 | m_ui(new Ui::MainWindow), 51 | m_hex(new QHexView), 52 | m_layout(new QVBoxLayout), 53 | m_dialog(), 54 | m_countRow(0), 55 | m_pid(0) 56 | { 57 | m_ui->setupUi(this); 58 | 59 | setWindowTitle(TITLE_WINDOW); 60 | setWindowIcon(QIcon(ICON_WINDOW)); 61 | setMinimumWidth(850); 62 | setMinimumHeight(680); 63 | 64 | // buttons conf 65 | conf_button_all(); 66 | 67 | // tables conf 68 | column_config_all(); 69 | 70 | // get type initial 71 | m_type = m_ui->type->currentIndex(); 72 | 73 | // set values for edit address and read 74 | set_types_edit_read(); 75 | 76 | // default theme 77 | on_ButtonLight_triggered(); 78 | } 79 | 80 | MainWindow::~MainWindow() 81 | { 82 | delete m_ui; 83 | delete m_layout; 84 | delete m_hex; 85 | } 86 | 87 | // ======================================================================= 88 | // Config all qt, buttons and columns 89 | // 90 | // ======================================================================= 91 | void MainWindow::conf_button_all() 92 | { 93 | // buttons for pass pid 94 | m_ui->pidButton->setIcon(QIcon(ICON_PASS_PID)); 95 | m_ui->pidButton2->setIcon(QIcon(ICON_PASS_PID)); 96 | m_ui->rpidButton->setIcon(QIcon(ICON_RPASS_PID)); 97 | m_ui->pidButton->setShortcut(QKeySequence("Ctrl+O")); 98 | m_ui->rpidButton->setShortcut(QKeySequence("Ctrl+R")); 99 | 100 | // buttons for clean 101 | m_ui->cleanButton->setIcon(QIcon(ICON_CLEAN)); 102 | m_ui->cleanButtonLog->setIcon(QIcon(ICON_CLEAN)); 103 | m_ui->cleanButton->setShortcut(QKeySequence("Ctrl+L")); 104 | 105 | // search button 106 | m_ui->searchButton->setIcon(QIcon(ICON_SEARCH)); 107 | m_ui->searchButton->setAutoDefault(true); 108 | m_ui->find->setPlaceholderText("Value"); 109 | 110 | // edit button 111 | m_ui->editButton->setIcon(QIcon(ICON_EDIT)); 112 | m_ui->value->setPlaceholderText("Value"); 113 | 114 | // about button 115 | m_ui->aboutButton->setIcon(QIcon(ICON_ABOUT)); 116 | 117 | // new button 118 | m_ui->newButton->setIcon(QIcon(ICON_NEW)); 119 | m_ui->newButton->setShortcut(QKeySequence("Ctrl+N")); 120 | 121 | // kill button 122 | m_ui->killButton->setIcon(QIcon(ICON_KILL)); 123 | m_ui->killButton->setShortcut(QKeySequence("Ctrl+K")); 124 | 125 | // stop / play button 126 | m_ui->stopButton->setIcon(QIcon(ICON_STOP)); 127 | m_ui->stopButton->setShortcut(QKeySequence("Ctrl+S")); 128 | 129 | // search address 130 | m_ui->search_address->setPlaceholderText("Address"); 131 | // search value maps 132 | m_ui->search_maps->setPlaceholderText("Value"); 133 | 134 | // hex button 135 | m_ui->gotooffsetButton->setIcon(QIcon(ICON_HEX)); 136 | m_ui->gotooffsetButton->setShortcut(QKeySequence("Ctrl+G")); 137 | 138 | // close 139 | m_ui->closeButton->setIcon(QIcon(ICON_CLOSE)); 140 | m_ui->closeButton->setShortcut(QKeySequence("Ctrl+Q")); 141 | 142 | // help 143 | m_ui->quickHelpButton->setIcon(QIcon(ICON_HELP)); 144 | m_ui->quickHelpButton->setShortcut(QKeySequence("Ctrl+H")); 145 | 146 | // full screen 147 | m_ui->FullScreenButton->setIcon(QIcon(ICON_SCREEN)); 148 | m_ui->FullScreenButton->setShortcut(QKeySequence("F11")); 149 | 150 | // save log 151 | m_ui->SaveLogButton->setIcon(QIcon(ICON_SAVE)); 152 | } 153 | 154 | /** 155 | * @brief clean all columns and delete rows 156 | * 157 | */ 158 | void MainWindow::column_clean_all() 159 | { 160 | setWindowTitle(TITLE_WINDOW); 161 | column_delete(m_ui->view_address); 162 | column_delete(m_ui->maps_table); 163 | m_ui->address_edit->setText(NULL_STR); 164 | m_hex->clear(); 165 | m_ui->foundAddr_label->setText("Found : 0"); 166 | m_ui->Process_label->setText("No Process Selected"); 167 | m_pid_name.clear(); 168 | m_pid_wchan.clear(); 169 | m_pid_exedir.clear(); 170 | m_pid_loginuid.clear(); 171 | m_pid_cmdline.clear(); 172 | m_ui->Process_List->clear(); 173 | m_ui->progressFind->reset(); 174 | m_ui->fileSize_label->setText("Size 0 Bytes"); 175 | 176 | for (int i = 10; i >= 0; i--) 177 | { 178 | m_ui->infos_addr->setItem(i, Address_on, new QTableWidgetItem(NULL_STR)); 179 | m_ui->infos_addr->setItem(i, Address_off, new QTableWidgetItem(NULL_STR)); 180 | m_ui->infos_addr->setItem(i, Size_map, new QTableWidgetItem("0")); 181 | m_ui->infos_addr->setItem(i, Flags, new QTableWidgetItem("----")); 182 | } 183 | 184 | for (int i = 0; i <= 16; i++) 185 | m_ui->elfheader_table->setItem(0, i, new QTableWidgetItem(CLEAN_ROW)); 186 | } 187 | 188 | void MainWindow::column_config_all() 189 | { 190 | // view address 191 | // m_ui->view_address->horizontalHeader()->setSectionResizeMode ( QHeaderView::Stretch ); 192 | m_ui->view_address->setShowGrid(false); 193 | m_ui->view_address->setEditTriggers(QAbstractItemView::NoEditTriggers); 194 | m_ui->view_address->verticalHeader()->setVisible(false); 195 | 196 | // infos addr heap and stack 197 | m_ui->infos_addr->horizontalHeader()->setSectionResizeMode(QHeaderView::Stretch); 198 | m_ui->infos_addr->setEditTriggers(QAbstractItemView::NoEditTriggers); 199 | m_ui->infos_addr->setShowGrid(false); 200 | 201 | // log infos 202 | m_ui->log_text->setReadOnly(true); 203 | 204 | // maps table 205 | // m_ui->maps_table->horizontalHeader()->setSectionResizeMode(QHeaderView::Stretch); 206 | m_ui->maps_table->setEditTriggers(QAbstractItemView::NoEditTriggers); 207 | m_ui->maps_table->verticalHeader()->setVisible(false); 208 | 209 | // hex dump 210 | m_layout->addWidget(m_hex); 211 | m_ui->HexViewTab->setLayout(m_layout); 212 | 213 | // config infos type OS 214 | m_sys_hostname = QString::fromStdString(m_mapper.get_utilsPid(HOSTNAME)); 215 | m_sys_osrealese = QString::fromStdString(m_mapper.get_utilsPid(OSREALESE)); 216 | m_sys_version = QString::fromStdString(m_mapper.get_utilsPid(VERSION)); 217 | m_sys_type = QString::fromStdString(m_mapper.get_utilsPid(TYPE)); 218 | 219 | // elf header 220 | m_ui->elfheader_table->horizontalHeader()->setSectionResizeMode(QHeaderView::Stretch); 221 | m_ui->elfheader_table->setEditTriggers(QAbstractItemView::NoEditTriggers); 222 | 223 | m_ui->Process_List->setReadOnly(true); 224 | } 225 | 226 | // ======================================================================= 227 | // Set Values in Columns 228 | // 229 | // ======================================================================= 230 | void MainWindow::set_values_column_heap() 231 | { 232 | m_ui->view_address->setShowGrid(false); 233 | m_ui->view_address->setEditTriggers(QAbstractItemView::NoEditTriggers); 234 | 235 | // infos_addr 236 | QString on = QString::number(m_mapper.get_addrOn(), 16); 237 | QString off = QString::number(m_mapper.get_addrOff(), 16); 238 | QString size = QString::number(m_mapper.get_sizeAddress()); 239 | QString flags = QString::fromStdString(m_mapper.get_Flags()); 240 | 241 | // set itens 242 | m_ui->infos_addr->setItem(0, Address_on, new QTableWidgetItem(on)); 243 | m_ui->infos_addr->setItem(0, Address_off, new QTableWidgetItem(off)); 244 | m_ui->infos_addr->setItem(0, Size_map, new QTableWidgetItem(size)); 245 | m_ui->infos_addr->setItem(0, Flags, new QTableWidgetItem(flags)); 246 | } 247 | 248 | void MainWindow::set_values_column_stack() 249 | { 250 | // infos_addr 251 | QString on = QString::number(m_mapper.get_addrOn(), 16); 252 | QString off = QString::number(m_mapper.get_addrOff(), 16); 253 | QString size = QString::number(m_mapper.get_sizeAddress()); 254 | QString flags = QString::fromStdString(m_mapper.get_Flags()); 255 | 256 | // set itens 257 | m_ui->infos_addr->setItem(1, Address_on, new QTableWidgetItem(on)); 258 | m_ui->infos_addr->setItem(1, Address_off, new QTableWidgetItem(off)); 259 | m_ui->infos_addr->setItem(1, Size_map, new QTableWidgetItem(size)); 260 | m_ui->infos_addr->setItem(1, Flags, new QTableWidgetItem(flags)); 261 | } 262 | 263 | void MainWindow::set_values_column_elf() 264 | { 265 | PElf(m_pid_exedir.toStdString().data()); 266 | ElfStruct(pelf); 267 | 268 | int classElf = pelf.classElf; 269 | 270 | m_ui->elfheader_table->setItem(0, e_magic, new QTableWidgetItem(QString("7f 45 4c 46"))); 271 | m_ui->elfheader_table->setItem(0, e_version, new QTableWidgetItem(QString::number((classElf == ELFCLASS64) ? pelf.elf64.Header->e_version : pelf.elf32.Header->e_version))); 272 | m_ui->elfheader_table->setItem(0, e_entry, new QTableWidgetItem(QString::number((classElf == ELFCLASS64) ? pelf.elf64.Header->e_entry : pelf.elf32.Header->e_entry, 16))); 273 | m_ui->elfheader_table->setItem(0, e_phoff, new QTableWidgetItem(QString::number((classElf == ELFCLASS64) ? pelf.elf64.Header->e_phoff : pelf.elf32.Header->e_phoff))); 274 | m_ui->elfheader_table->setItem(0, e_shoff, new QTableWidgetItem(QString::number((classElf == ELFCLASS64) ? pelf.elf64.Header->e_shoff : pelf.elf32.Header->e_shoff))); 275 | m_ui->elfheader_table->setItem(0, e_abiversion, new QTableWidgetItem(QString::number(ElfMagic()[EI_ABIVERSION]))); 276 | m_ui->elfheader_table->setItem(0, e_flags, new QTableWidgetItem(QString::number((classElf == ELFCLASS64) ? pelf.elf64.Header->e_flags : pelf.elf32.Header->e_flags))); 277 | m_ui->elfheader_table->setItem(0, e_shentsize, new QTableWidgetItem(QString::number((classElf == ELFCLASS64) ? pelf.elf64.Header->e_shentsize : pelf.elf32.Header->e_shentsize))); 278 | m_ui->elfheader_table->setItem(0, e_shnum, new QTableWidgetItem(QString::number((classElf == ELFCLASS64) ? pelf.elf64.Header->e_shnum : pelf.elf32.Header->e_shnum))); 279 | m_ui->elfheader_table->setItem(0, e_shstrndx, new QTableWidgetItem(QString::number((classElf == ELFCLASS64) ? pelf.elf64.Header->e_shstrndx : pelf.elf32.Header->e_shstrndx))); 280 | m_ui->elfheader_table->setItem(0, e_class, new QTableWidgetItem(QString((classElf == ELFCLASS64) ? "ELF64" : "ELF32"))); 281 | m_ui->elfheader_table->setItem(0, e_abi, new QTableWidgetItem(QString((ElfMagic()[EI_OSABI] == 0) ? "System V" : "Not identified"))); 282 | m_ui->elfheader_table->setItem(0, e_type, new QTableWidgetItem(QString((ElfMagic()[0x10] == ET_EXEC) ? "Executable File" : (ElfMagic()[0x10] == ET_REL) ? "Realocable File" 283 | : "Shared Object"))); 284 | m_ui->elfheader_table->setItem(0, e_machine, new QTableWidgetItem(QString((ElfMagic()[0x12] == EM_X86_64) ? "x86-64 Architecture" : (ElfMagic()[0x12] == EM_386) ? "x84_32 Architecture" 285 | : "Not identified"))); 286 | } 287 | 288 | /** 289 | * @brief set types possibles for search mem 290 | * 291 | */ 292 | void MainWindow::set_types_edit_read() 293 | { 294 | m_typeSizes.insert(std::make_pair("char", sizeof(char))); 295 | m_typeSizes.insert(std::make_pair("int", sizeof(int))); 296 | m_typeSizes.insert(std::make_pair("int16", sizeof(int16_t))); 297 | m_typeSizes.insert(std::make_pair("uint64", sizeof(uint64_t))); 298 | m_typeSizes.insert(std::make_pair("string", sizeof(std::string))); 299 | } 300 | 301 | // Big O(n²) 302 | void MainWindow::set_values_column_maps() 303 | { 304 | for (auto &x : m_unmap) 305 | { 306 | m_ui->maps_table->insertRow(m_ui->maps_table->rowCount()); 307 | int rowCount = m_ui->maps_table->rowCount() - 1; 308 | 309 | m_ui->maps_table->setItem(rowCount, Address_start, new QTableWidgetItem(QString::number(x.second.addr_on, 16))); 310 | m_ui->maps_table->setItem(rowCount, Address_stop, new QTableWidgetItem(QString::number(x.second.addr_off, 16))); 311 | m_ui->maps_table->setItem(rowCount, Perms, new QTableWidgetItem(QString::fromStdString(x.second.flags))); 312 | m_ui->maps_table->setItem(rowCount, Offset, new QTableWidgetItem(QString::number(x.second.offset))); 313 | m_ui->maps_table->setItem(rowCount, Pathname, new QTableWidgetItem(QString::fromStdString(x.second.pathname))); 314 | } 315 | } 316 | 317 | void MainWindow::set_values_process() 318 | { 319 | m_ui->Process_label->setText("Process"); 320 | m_ui->Process_List->setText("\t\tName : " + m_pid_name.trimmed() + "\t\tPid: " + QString::fromStdString(std::to_string(m_pid))); 321 | } 322 | 323 | /** 324 | * Big O(n²) 325 | * 326 | * @brief will set all addresses and values ​​found in the search 327 | * 328 | * @param p_offsets vector containing the address 329 | * @param value value find 330 | * @param memory memory in which the value was found 331 | */ 332 | void MainWindow::set_values_column_address(std::vector &p_offsets, std::string p_value, std::string p_memory) 333 | { 334 | int progress = 0; 335 | int valueMax = p_offsets.size(); 336 | m_ui->progressFind->reset(); 337 | m_ui->progressFind->setMaximum(valueMax); 338 | 339 | if (m_ui->CheckHex->isChecked()) 340 | p_value = "0x" + p_value; 341 | 342 | if (m_all_mapper) 343 | m_ui->view_address->setRowCount(m_countRow); 344 | else if (m_ui->view_address->rowCount() > 0) 345 | column_delete(m_ui->view_address); 346 | 347 | for (auto &x : p_offsets) 348 | { 349 | m_ui->view_address->insertRow(m_ui->view_address->rowCount()); 350 | int rowCount = m_ui->view_address->rowCount() - 1; 351 | 352 | QString addr = QString::number(x, 16); 353 | 354 | m_ui->view_address->setItem(rowCount, Address, new QTableWidgetItem(addr)); 355 | m_ui->view_address->setItem(rowCount, Value, new QTableWidgetItem(QString(QString::fromStdString(p_value)))); 356 | m_ui->view_address->setItem(rowCount, Memory, new QTableWidgetItem(QString(QString::fromStdString(p_memory)))); 357 | 358 | m_ui->progressFind->setValue(progress); 359 | progress++; 360 | } 361 | 362 | if (m_all_mapper) 363 | m_countRow = m_ui->view_address->rowCount(); 364 | 365 | m_ui->foundAddr_label->setText("Found : " + QString::number(m_ui->view_address->rowCount())); 366 | 367 | if (m_ui->progressFind->value() < valueMax) 368 | m_ui->progressFind->setValue(valueMax); 369 | } 370 | 371 | // ======================================================================= 372 | // Buttons clicked and actions 373 | // 374 | // ======================================================================= 375 | 376 | // style sheets 377 | void MainWindow::on_ButtonDark_triggered() 378 | { 379 | QFile f("../src/gui/style/dark.css"); 380 | 381 | if (!f.exists()) 382 | { 383 | std::string errorMessage("Loading Error: "); 384 | errorMessage.append("Error in load style dark, verify this file exist..."); 385 | 386 | QMessageBox msgBox; 387 | msgBox.setText(errorMessage.c_str()); 388 | msgBox.exec(); 389 | return; 390 | } 391 | else 392 | { 393 | f.open(QFile::ReadOnly | QFile::Text); 394 | QTextStream ts(&f); 395 | setStyleSheet(ts.readAll()); 396 | 397 | m_hex->setColorCharacters(Qt::white); 398 | m_hex->setColorAddress(QColor(30, 30, 30, 0xff)); 399 | } 400 | } 401 | 402 | void MainWindow::on_ButtonLight_triggered() 403 | { 404 | QFile f("../src/gui/style/light.css"); 405 | 406 | if (!f.exists()) 407 | { 408 | std::string errorMessage("Loading Error: "); 409 | errorMessage.append("Error in load style light, verify this file exist..."); 410 | 411 | QMessageBox msgBox; 412 | msgBox.setText(errorMessage.c_str()); 413 | msgBox.exec(); 414 | return; 415 | } 416 | else 417 | { 418 | f.open(QFile::ReadOnly | QFile::Text); 419 | QTextStream ts(&f); 420 | setStyleSheet(ts.readAll()); 421 | 422 | m_hex->setColorAddress(Qt::white); 423 | m_hex->setColorCharacters(Qt::black); 424 | } 425 | } 426 | 427 | void MainWindow::on_PidInfoButton_triggered() 428 | { 429 | if (m_pid_name.size() == 0) 430 | return; 431 | 432 | QString infos = "
Name :
" + m_pid_name + 433 | "\n
Command Line :
" + m_pid_cmdline + 434 | "\n
Login uid :
" + m_pid_loginuid + 435 | "\n
Binary Size :
" + m_pid_sizebin + 436 | "\n
Wchan :
" + m_pid_wchan; 437 | QMessageBox::about(nullptr, "Pid Info", infos); 438 | } 439 | 440 | /** 441 | * @brief clean log button 442 | * 443 | */ 444 | void MainWindow::on_cleanButtonLog_triggered() 445 | { 446 | m_ui->log_text->clear(); 447 | } 448 | 449 | /** 450 | * @brief stop process button 451 | * 452 | */ 453 | void MainWindow::on_stopButton_triggered() 454 | { 455 | if (m_pid_name.size() == 0) 456 | return; 457 | 458 | try 459 | { 460 | if (m_ui->stopButton->text() == "Stop Pid") 461 | { 462 | m_mapper.map_stop(); 463 | m_ui->stopButton->setText("Play Pid"); 464 | m_ui->stopButton->setIcon(QIcon(ICON_PLAY)); 465 | write_log("[SIGNAL STOP] you send a signal to the PID=" + QString::fromStdString(std::to_string(m_pid)) + ", sending it on a stop in the process") 466 | } 467 | else if (m_ui->stopButton->text() == "Play Pid") 468 | { 469 | m_mapper.map_stop(false); 470 | m_ui->stopButton->setText("Stop Pid"); 471 | m_ui->stopButton->setIcon(QIcon(ICON_STOP)); 472 | write_log("[SIGNAL RUNNING] you send a signal to the PID=" + QString::fromStdString(std::to_string(m_pid)) + ", sending it on a running in the process") 473 | } 474 | } 475 | catch (std::exception &error) 476 | { 477 | QMessageBox::critical(nullptr, "Error", error.what()); 478 | column_clean_all(); 479 | } 480 | } 481 | 482 | /** 483 | * @brief kill process button 484 | * 485 | */ 486 | void MainWindow::on_killButton_triggered() 487 | { 488 | if (m_pid_name.size() == 0) 489 | return; 490 | 491 | QMessageBox::StandardButton kill = QMessageBox::question(this, "SIGNAL KILL", "Kill Process " + m_pid_name + "? ", QMessageBox::Yes | QMessageBox::No); 492 | 493 | if (kill == QMessageBox::Yes) 494 | { 495 | m_pid = 0; 496 | m_mapper.map_kill(); 497 | column_clean_all(); 498 | write_log("[SIGNAL KILL] you send a signal to the PID=" + QString::fromStdString(std::to_string(m_pid)) + ", sending it on a kill in the process") 499 | } 500 | } 501 | 502 | void MainWindow::on_search_maps_textEdited(const QString &p_arg1) 503 | { 504 | for (int i = 0; i < m_ui->maps_table->rowCount(); i++) 505 | m_ui->maps_table->hideRow(i); 506 | 507 | QList search = m_ui->maps_table->findItems(p_arg1, Qt::MatchContains); 508 | 509 | foreach (auto &Ptr, search) 510 | { 511 | m_ui->maps_table->showRow(Ptr->row()); 512 | m_ui->foundAddr_label->setText("Found " + QString::number(search.size())); 513 | } 514 | 515 | if (p_arg1.size() == 0) 516 | m_ui->foundAddr_label->setText("Found " + QString::number(m_ui->maps_table->rowCount())); 517 | 518 | search.clear(); 519 | } 520 | 521 | /** 522 | * @brief search table view address 523 | * 524 | * @param arg1 search address table view_address 525 | */ 526 | void MainWindow::on_search_address_textEdited(const QString &p_arg1) 527 | { 528 | for (int i = 0; i < m_ui->view_address->rowCount(); i++) 529 | m_ui->view_address->hideRow(i); 530 | 531 | QList search = m_ui->view_address->findItems(p_arg1, Qt::MatchContains); 532 | 533 | foreach (auto &Ptr, search) 534 | m_ui->view_address->showRow(Ptr->row()); 535 | 536 | search.clear(); 537 | } 538 | 539 | /** 540 | * @brief set offset for jumṕ 541 | * */ 542 | void MainWindow::on_gotooffsetButton_triggered() 543 | { 544 | if (m_pid_name.size() == 0) 545 | return; 546 | 547 | bool done; 548 | QString offset = QInputDialog::getText(this, tr("Goto..."), 549 | tr("Offset (0x for hexadecimal):"), QLineEdit::Normal, 550 | nullptr, &done); 551 | 552 | if (done && offset[0] == '0' && offset[1] == 'x') 553 | m_hex->showFromOffset(offset.toInt(nullptr, 16)); 554 | else 555 | m_hex->showFromOffset(offset.toInt(nullptr)); 556 | } 557 | 558 | /** 559 | * @brief open browser for help maProc 560 | * */ 561 | void MainWindow::on_quickHelpButton_triggered() 562 | { 563 | try 564 | { 565 | QDesktopServices::openUrl(QUrl("https://github.com/mentebinaria/maProc/wiki/Help")); 566 | } 567 | catch (std::exception &e) 568 | { 569 | QMessageBox::warning(nullptr, "Warning", e.what()); 570 | } 571 | } 572 | 573 | /** 574 | * @brief full screen window 575 | * */ 576 | void MainWindow::on_FullScreenButton_triggered() 577 | { 578 | if (isFullScreen()) 579 | showNormal(); 580 | else 581 | showFullScreen(); 582 | } 583 | 584 | /** 585 | * @brief Save log 586 | * */ 587 | void MainWindow::on_SaveLogButton_triggered() 588 | { 589 | QString textLog = m_ui->log_text->toPlainText(); 590 | 591 | if (textLog.size() != 0) 592 | { 593 | QString fileName = QFileDialog::getSaveFileName(this, 594 | tr("Save Log maProc"), "", 595 | tr("maProc Logs (*.log);;All Files (*)")); 596 | 597 | if (fileName.isEmpty()) 598 | return; 599 | else 600 | { 601 | QFile file(fileName + ".log"); 602 | 603 | if (!file.open(QIODevice::WriteOnly)) 604 | { 605 | QMessageBox::information(this, tr("Unable to open file"), 606 | file.errorString()); 607 | return; 608 | } 609 | 610 | file.write(textLog.toStdString().data(), textLog.size()); 611 | } 612 | } 613 | else 614 | QMessageBox::critical(nullptr, "Error", "Logging is empty, active checkbox []Log"); 615 | } 616 | 617 | void MainWindow::on_SystemInfoButton_triggered() 618 | { 619 | 620 | QString infos = "
Host Name :
" + m_sys_hostname + 621 | "\n
Os realese :
" + m_sys_osrealese + 622 | "\n
Os Version :
" + m_sys_version + 623 | "\n
Os type :
" + m_sys_type; 624 | QMessageBox::about(nullptr, "System Info", infos); 625 | } 626 | 627 | void MainWindow::on_pidButton_triggered() 628 | { 629 | column_clean_all(); 630 | DirWindow dir; 631 | dir.exec(); 632 | 633 | m_pid = dir.getPid(); 634 | if (m_pid == 0) 635 | return; 636 | else 637 | mainMapper(); 638 | } 639 | 640 | void MainWindow::on_pidButton2_clicked() 641 | { 642 | on_pidButton_triggered(); 643 | } 644 | 645 | /** 646 | * @brief search value in fetch value from an address 647 | * on the stack or heap, will get the type using the combo box 648 | */ 649 | void MainWindow::on_searchButton_clicked() 650 | { 651 | m_all_mapper = false; 652 | std::string varType = m_ui->type->currentText().toStdString(); 653 | std::string find = m_ui->find->text().toStdString(); 654 | std::size_t mem = m_ui->mem->currentIndex(); 655 | auto it = m_typeSizes.find(varType); 656 | 657 | try 658 | { 659 | if (m_ui->CheckHex->isChecked() && it->second != sizeof(std::string)) 660 | find = std::to_string(stoul(find, nullptr, 16)); 661 | 662 | if (find.size() != 0 && m_pid != 0 && it != m_typeSizes.end()) 663 | { 664 | QTableWidgetItem *addr; 665 | off_t address_start; 666 | QTableWidgetItem *size; 667 | uint64_t lenght; 668 | std::vector offsets; 669 | 670 | switch (mem) 671 | { 672 | case 0: // stack 673 | stack: 674 | addr = m_ui->infos_addr->item(1, 0); 675 | size = m_ui->infos_addr->item(1, 2); 676 | 677 | if (addr->text().toStdString() != NULL_STR) 678 | { 679 | address_start = static_cast(std::stoul(addr->text().toStdString(), nullptr, 16)); 680 | lenght = std::stoul(size->text().toStdString(), nullptr); 681 | 682 | mapper_find(address_start, lenght, find, it->second, offsets); 683 | 684 | if (offsets.size() != 0) 685 | set_values_column_address(offsets, find, "[stack]"); 686 | } 687 | 688 | if (mem == 3) 689 | goto heap; 690 | 691 | break; 692 | 693 | case 1: // heap 694 | heap: 695 | addr = m_ui->infos_addr->item(0, 0); 696 | size = m_ui->infos_addr->item(0, 2); 697 | 698 | if (addr->text().toStdString() != NULL_STR) 699 | { 700 | address_start = static_cast(std::stoul(addr->text().toStdString(), nullptr, 16)); 701 | lenght = std::stoul(size->text().toStdString(), nullptr); 702 | 703 | mapper_find(address_start, lenght, find, it->second, offsets); 704 | 705 | if (offsets.size() != 0) 706 | set_values_column_address(offsets, find, "[heap]"); 707 | } 708 | 709 | if (mem == 3) 710 | goto personalization; 711 | 712 | break; 713 | 714 | case 2: // personalization 715 | { 716 | personalization: 717 | 718 | if (m_ui->StartAddress->text().size() != 0 && m_ui->StopAddress->text().size() != 0) 719 | { 720 | address_start = static_cast(std::stoul(m_ui->StartAddress->text().toStdString(), nullptr, 16)); 721 | off_t address_stop = static_cast(std::stoul(m_ui->StopAddress->text().toStdString(), nullptr, 16)); 722 | 723 | if (address_start < address_stop) 724 | { 725 | lenght = address_stop - address_start; 726 | mapper_find(address_start, lenght, find, it->second, offsets); 727 | } 728 | else 729 | QMessageBox::critical(nullptr, "Error", "Offsets invalids, consult tab maps"); 730 | 731 | if (offsets.size() != 0) 732 | set_values_column_address(offsets, find, "[personalization]"); 733 | } 734 | 735 | break; 736 | } 737 | 738 | case 3: // all 739 | m_all_mapper = true; 740 | goto stack; 741 | 742 | default: 743 | return; 744 | } 745 | } 746 | else if (it == m_typeSizes.end()) // critical error, will exit the program 747 | { 748 | QMessageBox::critical(nullptr, "Critical Error", "Error in code not possible find type\n verify unordered_map[TypeSizes]"); 749 | exit(EXIT_FAILURE); 750 | } 751 | } 752 | catch (std::exception &error) 753 | { 754 | QMessageBox::warning(nullptr, "Warning", "Verify offsets error unexpected, consult maps tab"); 755 | } 756 | } 757 | 758 | void MainWindow::on_closeButton_triggered() 759 | { 760 | QMessageBox::StandardButton close = QMessageBox::question(this, "Close", "Close this Program ?", QMessageBox::Yes | QMessageBox::No); 761 | 762 | if (close == QMessageBox::Yes) 763 | this->close(); 764 | } 765 | 766 | void MainWindow::on_cleanButton_triggered() 767 | { 768 | column_clean_all(); 769 | } 770 | 771 | /** 772 | * @brief new window 773 | * 774 | */ 775 | void MainWindow::on_newButton_triggered() 776 | { 777 | auto mm = new MainWindow(); 778 | mm->setAttribute(Qt::WA_DeleteOnClose); 779 | mm->show(); 780 | } 781 | 782 | /** 783 | * @brief edit address value 784 | * 785 | */ 786 | void MainWindow::on_editButton_clicked() 787 | { 788 | off_t address = valid_address_edit(); 789 | std::string varType = m_ui->type->currentText().toStdString(); 790 | auto it = m_typeSizes.find(varType); 791 | std::string value = m_ui->value->text().toStdString(); 792 | 793 | if (it != m_typeSizes.end() && address != 0 && m_pid != 0 && value.size() != 0) 794 | { 795 | std::size_t SizeT = (varType == "string") ? value.size() : it->second; 796 | 797 | if (m_ui->FillNullCheck->isChecked() && varType == "string") 798 | { 799 | if (SizeT < m_countFillNull) 800 | { 801 | for (int i = 0; i < m_countFillNull; i++) 802 | value += '\0'; 803 | 804 | SizeT = value.size(); 805 | } 806 | } 807 | 808 | if (m_mapper.map_write(address, (void *)&value[0], SizeT) == true) 809 | { 810 | write_log("[EDITED] Memory edited address [" + QString::number(address, 16) + "] [" + m_ui->find->text() + "] - > [" + QString::fromStdString(value) + "]"); 811 | } 812 | else 813 | { 814 | write_log("[ERROR] Fail edit memory [" + QString::number(address, 16) + "] [" + m_ui->find->text() + "] - > [" + QString::fromStdString(value) + "]"); 815 | } 816 | } 817 | else if (it == m_typeSizes.end()) 818 | { // critical error, will exit the program 819 | 820 | QMessageBox::critical(nullptr, "Critical Error", "Error in code not possible find type\n verify unordered_map[TypeSizes]"); 821 | exit(EXIT_FAILURE); 822 | } 823 | } 824 | 825 | /** 826 | * @brief repasser pid if cleaned infos 827 | * 828 | */ 829 | void MainWindow::on_rpidButton_triggered() 830 | { 831 | if (m_pid != 0) 832 | mainMapper(); 833 | } 834 | 835 | /** 836 | * @brief about button for infos copyright and project information 837 | * 838 | */ 839 | void MainWindow::on_aboutButton_triggered() 840 | { 841 | m_dialog.reset(new QDialog(this)); 842 | Ui_m_about aboutUi; 843 | aboutUi.setupUi(m_dialog.get()); 844 | 845 | m_dialog->showNormal(); 846 | } 847 | 848 | // ======================================================================= 849 | // Utils, clean columns and view columns, 850 | // verify pid and main mapper process and validatios 851 | // 852 | // ======================================================================= 853 | 854 | void MainWindow::mainMapper() 855 | { 856 | column_delete(m_ui->view_address); 857 | column_clean_all(); 858 | 859 | try 860 | { 861 | verify_pid(); 862 | 863 | if (m_pid != 0) 864 | { 865 | m_unmap = m_mapper.get_Maps(); 866 | 867 | set_values_column_elf(); 868 | set_values_process(); 869 | set_values_column_maps(); 870 | m_hex->loadFile(m_pid_exedir); 871 | m_ui->fileSize_label->setText("Size " + QString::number(m_hex->getFileSize()) + "Bytes"); 872 | 873 | if (mapper_stack) 874 | set_values_column_stack(); 875 | 876 | if (mapper_heap) 877 | set_values_column_heap(); 878 | } 879 | } 880 | catch (std::exception &error) 881 | { 882 | QMessageBox::warning(nullptr, "Warning", (std::string(error.what()) == "stoul") ? "Verify pid error unexpected" : error.what()); 883 | } 884 | } 885 | 886 | /** 887 | * @brief verify pid for mapper 888 | * 889 | */ 890 | void MainWindow::verify_pid() 891 | { 892 | if (m_mapper.map_pid(m_pid) == PID_SUCCESS) 893 | { 894 | m_pid_name = QString::fromStdString(m_mapper.get_utilsPid(NAME)); 895 | m_pid_cmdline = QString::fromStdString(m_mapper.get_utilsPid(CMDLINE)); 896 | m_pid_loginuid = QString::fromStdString(m_mapper.get_utilsPid(LOGINUID)); 897 | m_pid_sizebin = QString::fromStdString(m_mapper.get_utilsPid(SIZEBIN)); 898 | m_pid_wchan = QString::fromStdString(m_mapper.get_utilsPid(WCHAN)); 899 | m_pid_exedir = QString::fromStdString(m_mapper.get_utilsPid(EXEDIR)); 900 | m_pid_blocksize = QString::fromStdString(m_mapper.get_utilsPid(BLOCKSIZEBIN)); 901 | 902 | // tell the status bar which pid is being mapped 903 | setWindowTitle("maProc - PID: " + QString::fromStdString(std::to_string(m_pid)) + " Name: " + m_pid_name); 904 | } 905 | else 906 | m_pid = 0; 907 | } 908 | 909 | /** 910 | * @brief will try to fetch the information in memory 911 | * 912 | * @param p_addr start address for search 913 | * @param p_length size for read 914 | * @param p_find what to look for 915 | * @param p_type type for search 916 | * @param p_offsets will store the addresses found in a vector 917 | */ 918 | void MainWindow::mapper_find(off_t p_addr, off_t p_length, std::string p_find, 919 | uint8_t p_type, std::vector &p_offsets) 920 | { 921 | try 922 | { 923 | int valueMax = p_offsets.size(); 924 | m_countFillNull = p_find.size(); 925 | 926 | // search for locations that have 927 | // already been found in the table 928 | if (m_ui->checkCache->isChecked()) 929 | { 930 | 931 | // progress bar 932 | m_ui->progressFind->setValue(0); 933 | 934 | std::string find = m_ui->find->text().toStdString(); 935 | int rowCont = m_ui->view_address->rowCount(); 936 | std::size_t size = find.size(); 937 | 938 | Data data(size); 939 | 940 | for (int it = 0; it < rowCont; it++) 941 | { 942 | std::string str; 943 | off_t addr = std::stoul(m_ui->view_address->item(it, Address)->text().toStdString(), nullptr, 16); 944 | m_mapper.map_read(addr, size, data); 945 | 946 | for (int i = 0; i < data.m_size; i++) 947 | str += data.m_buff[i]; 948 | 949 | if (str == find) 950 | { 951 | m_ui->view_address->showRow(it); 952 | m_ui->view_address->setItem(it, Value, new QTableWidgetItem(QString(QString::fromStdString(find)))); 953 | } 954 | else 955 | m_ui->view_address->hideRow(it); 956 | 957 | m_ui->progressFind->setValue(it); 958 | } 959 | 960 | if (m_ui->progressFind->value() < valueMax) 961 | m_ui->progressFind->setValue(valueMax); 962 | 963 | data.clear(); 964 | } 965 | else 966 | { 967 | if (m_mapper.map_find(p_addr, p_length, p_find, p_type, p_offsets) == READ_FAIL) 968 | QMessageBox::critical(nullptr, "Error", "Not read memory, error in start " + QString::number(p_addr, 16)); 969 | } 970 | 971 | QString sizeFound = QString::fromStdString(std::to_string(valueMax)); 972 | write_log("[SEARCH] PID [" + QString::fromStdString(std::to_string(m_pid)) + "] searched in memory start [" + QString::number(p_addr, 16) + "] [" + QString::fromStdString(p_find) + "] found these addresses with such values [" + sizeFound + "]"); 973 | 974 | m_ui->foundAddr_label->setText("Found : " + sizeFound); 975 | } 976 | catch (std::exception &error) 977 | { 978 | m_ui->foundAddr_label->setText("Found : 0"); 979 | QMessageBox::critical(nullptr, "Error", error.what()); 980 | write_log("[ERROR] not read memory " + QString::fromStdString(error.what())); 981 | } 982 | } 983 | 984 | /** 985 | * @brief 986 | * 987 | * @return off_t if address valid return p_offsets, else address not valid return 0 988 | */ 989 | off_t MainWindow::valid_address_edit() 990 | { 991 | std::string address_edit = m_ui->address_edit->text().toStdString(); 992 | off_t address = 0; 993 | 994 | if (address_edit == NULL_STR) 995 | QMessageBox::critical(nullptr, "Error", "Address NULL not valid, set address valid for edit value"); 996 | else 997 | address = static_cast(std::stoul(address_edit, nullptr, 16)); 998 | 999 | return address; 1000 | } 1001 | 1002 | void MainWindow::on_maps_table_itemDoubleClicked(QTableWidgetItem *p_first) 1003 | { 1004 | if (m_pid_name.size() == 0) 1005 | return; 1006 | 1007 | QString AddressStart = m_ui->maps_table->item(p_first->row(), Address_start)->text(); 1008 | QString AddressStop = m_ui->maps_table->item(p_first->row(), Address_stop)->text(); 1009 | QString PathnameMemory = m_ui->maps_table->item(p_first->row(), Pathname)->text(); 1010 | 1011 | m_ui->StartAddress->setText(AddressStart); 1012 | m_ui->StopAddress->setText(AddressStop); 1013 | 1014 | write_log("[CLICKED] Address Start [" + AddressStart + "] Address Stop [" + AddressStop + "]" + " Memory [" + PathnameMemory + "]"); 1015 | } 1016 | 1017 | /** 1018 | * @brief set address for edit value 1019 | * 1020 | * @param p_first address double clicked 1021 | */ 1022 | void MainWindow::view_address_table(QTableWidgetItem *p_first) 1023 | { 1024 | if (m_pid_name.size() == 0) 1025 | return; 1026 | 1027 | QString selectedAddress = m_ui->view_address->item(p_first->row(), Address)->text(); 1028 | QString selectedValue = m_ui->view_address->item(p_first->row(), Value)->text(); 1029 | QString selectedMemory = m_ui->view_address->item(p_first->row(), Memory)->text(); 1030 | m_ui->address_edit->setText(selectedAddress); 1031 | 1032 | write_log("[CLICKED] Address [" + selectedAddress + "] Value [" + selectedValue + "]" + " Memory [" + selectedMemory + "]"); 1033 | } 1034 | 1035 | // ======================================================================= 1036 | // Thread and tasks window 1037 | // ======================================================================= 1038 | 1039 | void MainWindow::paintEvent(QPaintEvent *event) 1040 | { 1041 | if (m_hex->getFileSize() == 0) 1042 | return; 1043 | 1044 | auto offset = m_hex->getOffset(); 1045 | m_ui->offset_label->setText("0x" + QString::number(offset, 16)); 1046 | 1047 | m_ui->selecteds_label->setText("(Bytes " + QString::number(m_hex->getBytesSelecteds()) + " selected)"); 1048 | } -------------------------------------------------------------------------------- /src/mainwindow.hpp: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include 4 | #include 5 | #include 6 | #include 7 | #include 8 | #include 9 | #include 10 | #include 11 | 12 | #include "qhexview.hpp" 13 | #include "include/ps/ps.hpp" 14 | #include "include/map/pmap.hpp" 15 | #include "include/elf/relf.hpp" 16 | 17 | namespace Ui 18 | { 19 | class MainWindow; 20 | } 21 | 22 | class MainWindow : public QMainWindow 23 | { 24 | Q_OBJECT 25 | 26 | public: 27 | explicit MainWindow(QWidget * = nullptr); 28 | ~MainWindow(); 29 | 30 | void mainMapper(); 31 | pid_t m_pid; 32 | 33 | private slots: 34 | void verify_pid(); 35 | void mapper_find(off_t, off_t, std::string, 36 | uint8_t, std::vector &); 37 | 38 | off_t valid_address_edit(); 39 | void column_clean_all(); 40 | void conf_button_all(); 41 | void column_config_all(); 42 | void set_values_column_address(std::vector &, std::string, std::string); 43 | void on_maps_table_itemDoubleClicked(QTableWidgetItem *); 44 | void view_address_table(QTableWidgetItem *); 45 | void set_values_column_heap(); 46 | void set_values_column_stack(); 47 | void set_values_column_elf(); 48 | void set_types_edit_read(); 49 | void set_values_process(); 50 | void set_values_column_maps(); 51 | 52 | void on_search_address_textEdited(const QString &); 53 | void on_pidButton_triggered(); 54 | void on_searchButton_clicked(); 55 | void on_closeButton_triggered(); 56 | void on_newButton_triggered(); 57 | void on_cleanButton_triggered(); 58 | void on_editButton_clicked(); 59 | void on_aboutButton_triggered(); 60 | void on_gotooffsetButton_triggered(); 61 | void on_rpidButton_triggered(); 62 | void on_killButton_triggered(); 63 | void on_stopButton_triggered(); 64 | void on_cleanButtonLog_triggered(); 65 | void on_quickHelpButton_triggered(); 66 | void on_FullScreenButton_triggered(); 67 | void on_SaveLogButton_triggered(); 68 | void on_SystemInfoButton_triggered(); 69 | void on_pidButton2_clicked(); 70 | void on_PidInfoButton_triggered(); 71 | void on_search_maps_textEdited(const QString &p_arg1); 72 | void on_ButtonLight_triggered(); 73 | void on_ButtonDark_triggered(); 74 | void paintEvent(QPaintEvent *event); 75 | 76 | private: 77 | bool m_all_mapper; 78 | int m_type; 79 | int m_countRow; 80 | int m_countFillNull; 81 | 82 | QString m_pid_name; 83 | QString m_pid_cmdline; 84 | QString m_pid_loginuid; 85 | QString m_pid_sizebin; 86 | QString m_pid_wchan; 87 | QString m_pid_exedir; 88 | QString m_pid_blocksize; 89 | QString m_sys_hostname; 90 | QString m_sys_osrealese; 91 | QString m_sys_version; 92 | QString m_sys_type; 93 | 94 | std::unordered_map m_unmap; 95 | std::unordered_map m_typeSizes; 96 | Ui::MainWindow *m_ui; 97 | struct SELF pelf; 98 | Ps m_ps; 99 | Pmap m_mapper; 100 | QHexView *m_hex; 101 | QVBoxLayout *m_layout; 102 | std::shared_ptr m_dialog; 103 | }; 104 | -------------------------------------------------------------------------------- /src/qhexview.cpp: -------------------------------------------------------------------------------- 1 | #include "qhexview.hpp" 2 | 3 | #include 4 | #include 5 | #include 6 | #include 7 | #include 8 | #include 9 | #include 10 | #include 11 | #include 12 | #include 13 | 14 | #include 15 | 16 | // update 17 | #define UPDATE viewport()->update(); 18 | 19 | // valid character table ascii 20 | #define CHAR_VALID(caracter) \ 21 | ((caracter < 0x20) || (caracter > 0x7e)) ? caracter = '.' : caracter; 22 | 23 | // mark selection 24 | #define SET_BACKGROUND_MARK(pos) \ 25 | if (pos >= m_selectBegin && pos < m_selectEnd) \ 26 | { \ 27 | painter.setBackground(QBrush(QColor(COLOR_SELECTION))); \ 28 | painter.setBackgroundMode(Qt::OpaqueMode); \ 29 | } 30 | 31 | QHexView::QHexView(QWidget *parent) 32 | : QAbstractScrollArea(parent), 33 | m_pdata(nullptr), 34 | m_posAddr(0), 35 | m_charWidth(0), 36 | m_posHex(ADR_LENGTH * m_charWidth + GAP_ADR_HEX), 37 | m_posAscii(m_posHex + MIN_HEXCHARS_IN_LINE * m_charWidth + GAP_HEX_ASCII), 38 | m_bytesPerLine(MIN_BYTES_PER_LINE), 39 | m_charHeight(0), 40 | m_selectBegin(0), 41 | m_selectEnd(0), 42 | m_selectInit(0), 43 | m_cursorPos(0) 44 | { 45 | // default configs 46 | setFont(QFont(FONT, SIZE_FONT)); // default font 47 | } 48 | 49 | QHexView::~QHexView() {} 50 | 51 | void QHexView::loadFile(QString p_file) 52 | { 53 | QFile qFile; 54 | 55 | qFile.setFileName(p_file); 56 | 57 | qFile.open(QFile::ReadOnly); 58 | 59 | if (qFile.isOpen()) 60 | { 61 | setCursorPos(0); 62 | resetSelection(0); 63 | 64 | m_pdata = qFile.readAll(); 65 | 66 | qFile.close(); 67 | } 68 | else 69 | throw std::runtime_error("Falied to open file " + p_file.toStdString() + " not possible len bin"); 70 | 71 | resetSelection(0); 72 | } 73 | 74 | // search and set offset 75 | void QHexView::showFromOffset(int offset) 76 | { 77 | if (offset <= m_pdata.size()) 78 | { 79 | updatePositions(); 80 | 81 | setCursorPos(offset * 2); 82 | setSelected(offset, 1); 83 | 84 | int cursorY = m_cursorPos / (2 * m_bytesPerLine); 85 | 86 | verticalScrollBar()->setValue(cursorY); 87 | UPDATE 88 | } 89 | else 90 | throw std::runtime_error("Offset invalid, verify offset " + std::to_string(offset)); 91 | } 92 | 93 | // clean all 94 | void QHexView::clear() 95 | { 96 | verticalScrollBar()->setValue(0); 97 | m_pdata.clear(); 98 | UPDATE; 99 | } 100 | 101 | QSize QHexView::fullSize() const 102 | { 103 | if (m_pdata.size() == 0) 104 | return QSize(0, 0); 105 | 106 | int width = m_posAscii + (m_bytesPerLine * m_charWidth); 107 | int height = m_pdata.size() / m_bytesPerLine; 108 | 109 | if (m_pdata.size() % m_bytesPerLine) 110 | height++; 111 | 112 | height *= m_charHeight; 113 | 114 | return QSize(width, height); 115 | } 116 | 117 | void QHexView::updatePositions() 118 | { 119 | #if QT_VERSION >= 0x50f03 120 | m_charWidth = fontMetrics().horizontalAdvance(QLatin1Char('9')); 121 | #else 122 | m_charWidth = fontMetrics().width(QLatin1Char('9')); 123 | #endif 124 | 125 | m_charHeight = fontMetrics().height(); 126 | 127 | int serviceSymbolsWidth = ADR_LENGTH * m_charWidth + GAP_ADR_HEX + GAP_HEX_ASCII; 128 | 129 | m_bytesPerLine = (width() - serviceSymbolsWidth) / (4 * m_charWidth) - 1; // 4 symbols per byte 130 | 131 | if (m_bytesPerLine < 5) // avoid floating point 132 | m_bytesPerLine = 5; 133 | 134 | m_posAddr = 0; 135 | m_posHex = ADR_LENGTH * m_charWidth + GAP_ADR_HEX; 136 | m_posAscii = m_posHex + (m_bytesPerLine * 3 - 1) * m_charWidth + GAP_HEX_ASCII; 137 | } 138 | 139 | /*****************************************************************************/ 140 | /* Paint Hex View */ 141 | /*****************************************************************************/ 142 | void QHexView::paintEvent(QPaintEvent *event) 143 | { 144 | QPainter painter(viewport()); 145 | 146 | updatePositions(); 147 | 148 | int firstLineIdx = verticalScrollBar()->value(); 149 | int lastLineIdx = firstLineIdx + viewport()->size().height() / m_charHeight; 150 | 151 | int linePos = m_posAscii - (GAP_HEX_ASCII / 2); 152 | int yPosStart = m_charHeight; 153 | QBrush def = painter.brush(); 154 | 155 | // paint background address 156 | painter.fillRect(event->rect(), this->palette().color(QPalette::Base)); 157 | painter.fillRect(QRect(m_posAddr, event->rect().top(), m_posHex - GAP_ADR_HEX + 10, height()), m_colorAddress); 158 | painter.setBackgroundMode(Qt::OpaqueMode); 159 | 160 | // paint line separate ascii 161 | painter.setPen(m_colorAddress); 162 | painter.drawLine(linePos, event->rect().top(), linePos, height()); 163 | 164 | const QByteArray data = m_pdata.mid(firstLineIdx * m_bytesPerLine, (lastLineIdx - firstLineIdx) * m_bytesPerLine); 165 | 166 | painter.setPen(m_colorCharacter); // paint white characters and binary 167 | 168 | if (m_pdata.size() == 0) 169 | return; 170 | 171 | confScrollBar(); 172 | 173 | for (int lineIdx = firstLineIdx, yPos = yPosStart; lineIdx < lastLineIdx; 174 | lineIdx += 1, yPos += m_charHeight) 175 | { 176 | // ascii position 177 | for (int xPosAscii = m_posAscii, i = 0; 178 | ((lineIdx - firstLineIdx) * m_bytesPerLine + i) < data.size() && 179 | (i < m_bytesPerLine); 180 | i++, xPosAscii += m_charWidth) 181 | { 182 | SET_BACKGROUND_MARK((lineIdx * m_bytesPerLine + i) * 2); 183 | 184 | char character = data[(lineIdx - firstLineIdx) * (uint)m_bytesPerLine + i]; 185 | CHAR_VALID(character); 186 | 187 | painter.drawText(xPosAscii, yPos, QString(character)); 188 | 189 | painter.setBackground(painter.brush()); 190 | painter.setBackgroundMode(Qt::OpaqueMode); 191 | } 192 | 193 | // binary position 194 | for (int xPos = m_posHex, i = 0; i < m_bytesPerLine && 195 | ((lineIdx - firstLineIdx) * m_bytesPerLine + i) < data.size(); 196 | i++, xPos += 3 * m_charWidth) 197 | { 198 | SET_BACKGROUND_MARK((lineIdx * m_bytesPerLine + i) * 2); 199 | 200 | QString val = QString::number((data.at((lineIdx - firstLineIdx) * m_bytesPerLine + i) & 0xF0) >> 4, 16); 201 | painter.drawText(xPos, yPos, val); 202 | 203 | val = QString::number((data.at((lineIdx - firstLineIdx) * m_bytesPerLine + i) & 0xF), 16); 204 | painter.drawText(xPos + m_charWidth, yPos, val); 205 | 206 | painter.setBackground(painter.brush()); 207 | painter.setBackgroundMode(Qt::OpaqueMode); 208 | } 209 | 210 | // offsets 211 | QString address = QString("%1:").arg(lineIdx * m_bytesPerLine, 10, 16, QChar('0')); 212 | painter.drawText(m_posAddr, yPos, address); 213 | 214 | // cursor drawn 215 | if (hasFocus()) 216 | { 217 | int x = (m_cursorPos % (2 * m_bytesPerLine)); 218 | int y = m_cursorPos / (2 * m_bytesPerLine); 219 | y -= firstLineIdx; 220 | int cursorX = (((x / 2) * 3) + (x % 2)) * m_charWidth + m_posHex; 221 | int cursorY = y * m_charHeight + 4; 222 | 223 | painter.drawRoundedRect(QRectF(cursorX, cursorY, 18, m_charHeight), 0, 0); 224 | } 225 | } 226 | } 227 | 228 | void QHexView::keyPressEvent(QKeyEvent *event) 229 | { 230 | bool setVisible = false; 231 | 232 | /*****************************************************************************/ 233 | /* Cursor movements */ 234 | /*****************************************************************************/ 235 | if (event->matches(QKeySequence::MoveToNextChar)) 236 | { 237 | setCursorPos(m_cursorPos + 2); 238 | resetSelection(m_cursorPos); 239 | setVisible = true; 240 | } 241 | 242 | if (event->matches(QKeySequence::MoveToPreviousChar)) 243 | { 244 | setCursorPos(m_cursorPos - 2); 245 | resetSelection(m_cursorPos); 246 | setVisible = true; 247 | } 248 | 249 | if (event->matches(QKeySequence::MoveToEndOfLine)) 250 | { 251 | setCursorPos(m_cursorPos | ((m_bytesPerLine * 2) - 2)); 252 | resetSelection(m_cursorPos); 253 | setVisible = true; 254 | } 255 | 256 | if (event->matches(QKeySequence::MoveToStartOfLine)) 257 | { 258 | setCursorPos(m_cursorPos | (m_cursorPos % (m_bytesPerLine * 2))); 259 | resetSelection(m_cursorPos); 260 | setVisible = true; 261 | } 262 | 263 | if (event->matches(QKeySequence::MoveToPreviousLine)) 264 | { 265 | setCursorPos(m_cursorPos - m_bytesPerLine * 2); 266 | resetSelection(m_cursorPos); 267 | setVisible = true; 268 | } 269 | 270 | if (event->matches(QKeySequence::MoveToNextLine)) 271 | { 272 | setCursorPos(m_cursorPos + m_bytesPerLine * 2); 273 | resetSelection(m_cursorPos); 274 | setVisible = true; 275 | } 276 | 277 | if (event->matches(QKeySequence::MoveToNextPage)) 278 | { 279 | setCursorPos(m_cursorPos + (viewport()->height() / m_charHeight - 2) * 280 | 2 * m_bytesPerLine); 281 | resetSelection(m_cursorPos); 282 | setVisible = true; 283 | } 284 | 285 | if (event->matches(QKeySequence::MoveToPreviousPage)) 286 | { 287 | setCursorPos(m_cursorPos - (viewport()->height() / m_charHeight - 2) * 288 | 2 * m_bytesPerLine); 289 | resetSelection(m_cursorPos); 290 | setVisible = true; 291 | } 292 | 293 | if (event->matches(QKeySequence::MoveToEndOfDocument)) 294 | { 295 | if (m_pdata.size()) 296 | setCursorPos(m_pdata.size() * 2); 297 | 298 | resetSelection(m_cursorPos); 299 | setVisible = true; 300 | } 301 | 302 | if (event->matches(QKeySequence::MoveToStartOfDocument)) 303 | { 304 | setCursorPos(0); 305 | resetSelection(m_cursorPos); 306 | setVisible = true; 307 | } 308 | 309 | /*****************************************************************************/ 310 | /* Select commands */ 311 | /*****************************************************************************/ 312 | if (event->matches(QKeySequence::SelectAll)) 313 | { 314 | resetSelection(0); 315 | 316 | if (m_pdata.size()) 317 | setSelection(2 * m_pdata.size() + 2); 318 | 319 | setVisible = true; 320 | } 321 | 322 | if (event->matches(QKeySequence::SelectNextChar)) 323 | { 324 | int pos = m_cursorPos + 2; 325 | setCursorPos(pos); 326 | setSelection(pos); 327 | setVisible = true; 328 | } 329 | 330 | if (event->matches(QKeySequence::SelectPreviousChar)) 331 | { 332 | int pos = m_cursorPos - 2; 333 | setSelection(pos); 334 | setCursorPos(pos); 335 | setVisible = true; 336 | } 337 | 338 | if (event->matches(QKeySequence::SelectEndOfLine)) 339 | { 340 | int pos = m_cursorPos - (m_cursorPos % (2 * m_bytesPerLine)) + 341 | (2 * m_bytesPerLine); 342 | setCursorPos(pos); 343 | setSelection(pos); 344 | setVisible = true; 345 | } 346 | 347 | if (event->matches(QKeySequence::SelectStartOfLine)) 348 | { 349 | int pos = m_cursorPos - (m_cursorPos % (2 * m_bytesPerLine)); 350 | setCursorPos(pos); 351 | setSelection(pos); 352 | setVisible = true; 353 | } 354 | 355 | if (event->matches(QKeySequence::SelectPreviousLine)) 356 | { 357 | int pos = m_cursorPos - (2 * m_bytesPerLine); 358 | setCursorPos(pos); 359 | setSelection(pos); 360 | setVisible = true; 361 | } 362 | 363 | if (event->matches(QKeySequence::SelectNextLine)) 364 | { 365 | int pos = m_cursorPos + (2 * m_bytesPerLine); 366 | setCursorPos(pos); 367 | setSelection(pos); 368 | setVisible = true; 369 | } 370 | 371 | if (event->matches(QKeySequence::SelectNextPage)) 372 | { 373 | int pos = m_cursorPos + (((viewport()->height() / m_charHeight) - 2) * 374 | 2 * m_bytesPerLine); 375 | setCursorPos(pos); 376 | setSelection(pos); 377 | setVisible = true; 378 | } 379 | 380 | if (event->matches(QKeySequence::SelectPreviousPage)) 381 | { 382 | int pos = m_cursorPos - (((viewport()->height() / m_charHeight) - 2) * 383 | 2 * m_bytesPerLine); 384 | setCursorPos(pos); 385 | setSelection(pos); 386 | setVisible = true; 387 | } 388 | 389 | if (event->matches(QKeySequence::SelectEndOfDocument)) 390 | { 391 | int pos = 0; 392 | 393 | if (m_pdata.size()) 394 | pos = m_pdata.size() * 2; 395 | 396 | setCursorPos(pos); 397 | setSelection(pos); 398 | setVisible = true; 399 | } 400 | 401 | if (event->matches(QKeySequence::SelectStartOfDocument)) 402 | { 403 | int pos = 0; 404 | setCursorPos(pos); 405 | setSelection(pos); 406 | setVisible = true; 407 | } 408 | 409 | if (event->matches(QKeySequence::Copy)) 410 | copyBytes(); 411 | 412 | if (setVisible) 413 | ensureVisible(); 414 | 415 | UPDATE; 416 | } 417 | 418 | void QHexView::mouseMoveEvent(QMouseEvent *event) 419 | { 420 | int actPos = cursorPos(event->pos()); 421 | 422 | if (actPos != std::numeric_limits::max()) 423 | { 424 | setCursorPos(actPos); 425 | setSelection(actPos); 426 | } 427 | 428 | UPDATE; 429 | } 430 | 431 | void QHexView::mousePressEvent(QMouseEvent *event) 432 | { 433 | if (event->button() == Qt::RightButton) 434 | { 435 | event->ignore(); 436 | return; 437 | } 438 | 439 | int cPos = cursorPos(event->pos()); 440 | 441 | if ((QApplication::keyboardModifiers() & Qt::ShiftModifier)) 442 | setSelection(cPos); 443 | else 444 | resetSelection(cPos); 445 | 446 | if (cPos != std::numeric_limits::max()) 447 | setCursorPos(cPos); 448 | 449 | UPDATE; 450 | } 451 | 452 | int QHexView::cursorPos(const QPoint &position) 453 | { 454 | int pos = std::numeric_limits::max(); 455 | 456 | if (((int)position.x() >= m_posHex) && 457 | ((int)position.x() < 458 | (m_posHex + (m_bytesPerLine * 3 - 1) * m_charWidth))) 459 | { 460 | int x = (position.x() - m_posHex) / m_charWidth; 461 | 462 | ((x % 3) == 0) ? x = (x / 3) * 2 : x = ((x / 3) * 2) + 2; 463 | 464 | int firstLineIdx = verticalScrollBar()->value(); 465 | int y = (position.y() / m_charHeight) * 2 * m_bytesPerLine; 466 | pos = x + y + firstLineIdx * m_bytesPerLine * 2; 467 | } 468 | 469 | return pos; 470 | } 471 | 472 | void QHexView::resetSelection() 473 | { 474 | m_selectBegin = m_selectInit; 475 | m_selectEnd = m_selectInit; 476 | } 477 | 478 | void QHexView::resetSelection(int pos) 479 | { 480 | if (pos == std::numeric_limits::max()) 481 | pos = 0; 482 | 483 | m_selectInit = pos; 484 | m_selectBegin = pos; 485 | m_selectEnd = pos; 486 | } 487 | 488 | void QHexView::setSelection(int pos) 489 | { 490 | if (pos == std::numeric_limits::max()) 491 | pos = 0; 492 | 493 | if (pos >= m_selectInit) 494 | { 495 | m_selectEnd = pos; 496 | m_selectBegin = m_selectInit; 497 | } 498 | else 499 | { 500 | m_selectBegin = pos; 501 | m_selectEnd = m_selectInit; 502 | } 503 | } 504 | 505 | void QHexView::setSelected(int offset, int length) 506 | { 507 | m_selectInit = m_selectBegin = offset * 2; 508 | m_selectEnd = m_selectBegin + length * 2; 509 | 510 | setCursorPos(offset * 2); 511 | UPDATE 512 | } 513 | 514 | void QHexView::setCursorPos(int position) 515 | { 516 | if (position == std::numeric_limits::max()) 517 | position = 0; 518 | 519 | int maxPos = 0; 520 | 521 | if (m_pdata.size() != 0) 522 | { 523 | maxPos = m_pdata.size() * 2; 524 | 525 | if (m_pdata.size() % m_bytesPerLine) 526 | maxPos += 1; 527 | } 528 | 529 | if (position > maxPos) 530 | position = maxPos; 531 | 532 | m_cursorPos = position; 533 | } 534 | 535 | unsigned int QHexView::getOffset() 536 | { 537 | return m_cursorPos / 2; 538 | } 539 | 540 | void QHexView::ensureVisible() 541 | { 542 | QSize areaSize = viewport()->size(); 543 | 544 | int firstLineIdx = verticalScrollBar()->value(); 545 | int lastLineIdx = firstLineIdx + areaSize.height() / m_charHeight; 546 | 547 | int cursorY = m_cursorPos / (2 * m_bytesPerLine); 548 | 549 | if (cursorY < firstLineIdx) 550 | verticalScrollBar()->setValue(cursorY); 551 | else if (cursorY >= lastLineIdx) 552 | verticalScrollBar()->setValue(cursorY - areaSize.height() / m_charHeight + 1); 553 | } 554 | 555 | void QHexView::confScrollBar() 556 | { 557 | QSize areaSize = viewport()->size(); 558 | QSize widgetSize = fullSize(); 559 | verticalScrollBar()->setPageStep(areaSize.height() / m_charHeight); 560 | verticalScrollBar()->setRange(0, (widgetSize.height() - areaSize.height()) / m_charHeight + 1); 561 | } 562 | 563 | void QHexView::copyBytes() 564 | { 565 | if (m_pdata.size()) 566 | { 567 | QString res; 568 | int idx = 0; 569 | int copyOffset = 0; 570 | 571 | QByteArray data = m_pdata.mid(m_selectBegin / 2, 572 | (m_selectEnd - m_selectBegin) / 2 + 2); 573 | 574 | if (m_selectBegin % 2) 575 | { 576 | res += QString::number((data.at((idx + 2) / 2) & 0xF), 16); 577 | res += " "; 578 | idx++; 579 | copyOffset = 1; 580 | } 581 | 582 | int selectedSize = m_selectEnd - m_selectBegin; 583 | 584 | for (; idx < selectedSize; idx += 2) 585 | { 586 | if (data.size() > (copyOffset + idx) / 2) 587 | { 588 | QString val = QString::number( 589 | (data.at((copyOffset + idx) / 2) & 0xF0) >> 4, 16); 590 | 591 | if (idx + 2 < selectedSize) 592 | { 593 | val += QString::number( 594 | (data.at((copyOffset + idx) / 2) & 0xF), 16); 595 | val += " "; 596 | } 597 | 598 | res += val; 599 | 600 | if ((idx / 2) % m_bytesPerLine == (m_bytesPerLine - 1)) 601 | res += "\n"; 602 | } 603 | } 604 | 605 | QClipboard *clipboard = QApplication::clipboard(); 606 | clipboard->setText(res); 607 | } 608 | } 609 | 610 | void QHexView::setColorCharacters(const QColor &color) 611 | { 612 | m_colorCharacter = color; 613 | } 614 | 615 | void QHexView::setColorAddress(const QColor &color) 616 | { 617 | m_colorAddress = color; 618 | } 619 | 620 | unsigned int QHexView::getBytesSelecteds() 621 | { 622 | return (m_selectEnd - m_selectInit) / 2; 623 | } 624 | 625 | unsigned int QHexView::getFileSize() 626 | { 627 | return m_pdata.size(); 628 | } -------------------------------------------------------------------------------- /src/qhexview.hpp: -------------------------------------------------------------------------------- 1 | /** 2 | * @file QHexView.cpp 3 | * @author VitorMob 2022 4 | * @date 15 Mar 2022 5 | * @copyright 2022 VitorMob, 2015 virinext 6 | * @brief simple hex view / editor 7 | */ 8 | 9 | #pragma once 10 | 11 | #include 12 | #include 13 | #include 14 | 15 | // config font 16 | #define FONT "Consolas" 17 | #define SIZE_FONT 11 18 | #define COLOR_SELECTION 98, 114, 164, 0xff 19 | 20 | // config lines 21 | #define MIN_HEXCHARS_IN_LINE 47 22 | #define GAP_ADR_HEX 10 23 | #define GAP_HEX_ASCII 16 24 | #define MIN_BYTES_PER_LINE 16 25 | #define ADR_LENGTH 10 26 | 27 | class QHexView : public QAbstractScrollArea 28 | { 29 | Q_OBJECT 30 | public: 31 | QHexView(QWidget *parent = nullptr); 32 | ~QHexView(); 33 | 34 | protected: 35 | void paintEvent(QPaintEvent *event); 36 | void keyPressEvent(QKeyEvent *event); 37 | void mouseMoveEvent(QMouseEvent *event); 38 | void mousePressEvent(QMouseEvent *event); 39 | 40 | private: 41 | QByteArray m_pdata; 42 | 43 | unsigned int m_posAddr, 44 | m_posHex, 45 | m_posAscii, 46 | m_charWidth, 47 | m_charHeight, 48 | m_selectBegin, 49 | m_selectEnd, 50 | m_selectInit, 51 | m_cursorPos, 52 | m_bytesPerLine; 53 | 54 | QColor m_colorCharacter; 55 | QColor m_colorAddress; 56 | 57 | QSize fullSize() const; 58 | void updatePositions(); 59 | void resetSelection(); 60 | void resetSelection(int pos); 61 | void setSelection(int pos); 62 | void ensureVisible(); 63 | void setCursorPos(int pos); 64 | int cursorPos(const QPoint &position); 65 | void paintMark(int xpos, int ypos); 66 | void confScrollBar(); 67 | void copyBytes(); 68 | 69 | public slots: 70 | void loadFile(QString p_file); 71 | void clear(); 72 | void showFromOffset(int offset); 73 | void setSelected(int offset, int length); 74 | unsigned int getOffset(); 75 | void setColorCharacters(const QColor &color); 76 | void setColorAddress(const QColor &color); 77 | unsigned int getBytesSelecteds(); 78 | unsigned int getFileSize(); 79 | }; 80 | --------------------------------------------------------------------------------