Add sources
This commit is contained in:
parent
33ba219cb6
commit
9e7e278f0b
|
@ -0,0 +1,19 @@
|
|||
cmake_minimum_required(VERSION 3.0)
|
||||
|
||||
project(xcursor-viewer CXX)
|
||||
|
||||
set(CMAKE_AUTOMOC ON)
|
||||
set(CMAKE_AUTOUIC ON)
|
||||
|
||||
set(CMAKE_INCLUDE_CURRENT_DIR ON)
|
||||
|
||||
find_package(Qt5Core REQUIRED)
|
||||
find_package(Qt5Gui REQUIRED)
|
||||
find_package(Qt5Widgets REQUIRED)
|
||||
|
||||
set(SOURCES main.cpp dialog.cpp)
|
||||
set(HEADERS dialog.h)
|
||||
set(FORMS dialog.ui)
|
||||
|
||||
add_executable(${PROJECT_NAME} ${SOURCES} ${HEADERS} ${FORMS})
|
||||
target_link_libraries(${PROJECT_NAME} Qt5::Core Qt5::Gui Qt5::Widgets)
|
|
@ -0,0 +1,184 @@
|
|||
/*
|
||||
* Copyright (C) 2019 Ivan Romanov <drizt72@zoho.eu>
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
*/
|
||||
|
||||
#include "dialog.h"
|
||||
#include <ui_dialog.h>
|
||||
|
||||
#include <QBuffer>
|
||||
#include <QDataStream>
|
||||
#include <QDebug>
|
||||
#include <QDir>
|
||||
#include <QFile>
|
||||
#include <QFileDialog>
|
||||
|
||||
Dialog::Dialog(QWidget *parent)
|
||||
: QDialog(parent)
|
||||
, ui(new Ui::Dialog)
|
||||
{
|
||||
ui->setupUi(this);
|
||||
|
||||
connect(ui->lwCursors, &QListWidget::currentTextChanged, this, &Dialog::showCursor);
|
||||
connect(ui->pbOpenFolder, &QPushButton::clicked, this, &Dialog::openFolder);
|
||||
}
|
||||
|
||||
Dialog::~Dialog()
|
||||
{
|
||||
delete ui;
|
||||
}
|
||||
|
||||
void Dialog::openFolder()
|
||||
{
|
||||
QString dirPath = QFileDialog::getExistingDirectory(this);
|
||||
|
||||
if (dirPath.isEmpty()) {
|
||||
return;
|
||||
}
|
||||
|
||||
QDir dir(dirPath);
|
||||
|
||||
QStringList fileList = dir.entryList(QDir::Filter::Files);
|
||||
|
||||
_cursorFileList.clear();
|
||||
|
||||
for (const QString &fileName: fileList) {
|
||||
QFile file(dir.absoluteFilePath(fileName));
|
||||
if (!file.open(QIODevice::OpenModeFlag::ReadOnly)) {
|
||||
continue;
|
||||
}
|
||||
|
||||
QDataStream stream(&file);
|
||||
stream.setByteOrder(QDataStream::ByteOrder::LittleEndian);
|
||||
|
||||
quint32 magic;
|
||||
quint32 header;
|
||||
quint32 version;
|
||||
quint32 ntoc;
|
||||
|
||||
stream >> magic >> header >> version >> ntoc;
|
||||
|
||||
if (magic != 0x72756358 /* Xcur */ && header != 16) {
|
||||
continue;
|
||||
}
|
||||
|
||||
CursorFile cursorFile;
|
||||
|
||||
cursorFile.name = fileName;
|
||||
|
||||
for (quint32 i = 0; i < ntoc; ++i) {
|
||||
quint32 type;
|
||||
quint32 subtype;
|
||||
quint32 position;
|
||||
|
||||
stream >> type >> subtype >> position;
|
||||
qint64 tocPos = file.pos(); // position in table of contents entries
|
||||
|
||||
if (type == 0xfffd0002) {
|
||||
file.seek(position);
|
||||
|
||||
quint32 imgHeader;
|
||||
quint32 imgType;
|
||||
quint32 imgSubtype;
|
||||
quint32 imgVersion;
|
||||
quint32 imgWidth;
|
||||
quint32 imgHeight;
|
||||
quint32 imgYhot;
|
||||
quint32 imgXhot;
|
||||
quint32 imgDelay;
|
||||
|
||||
stream >> imgHeader
|
||||
>> imgType
|
||||
>> imgSubtype
|
||||
>> imgVersion
|
||||
>> imgWidth
|
||||
>> imgHeight
|
||||
>> imgYhot
|
||||
>> imgXhot
|
||||
>> imgDelay;
|
||||
|
||||
if (imgHeader != 36 || imgType != type || imgSubtype != subtype || imgVersion != 1) {
|
||||
continue;
|
||||
}
|
||||
|
||||
QByteArray imgData = file.read((imgWidth * imgHeight) * 4);
|
||||
|
||||
Cursor cursor;
|
||||
cursor.image = QImage(reinterpret_cast<uchar*>(imgData.data()), static_cast<int>(imgWidth), static_cast<int>(imgHeight), QImage::Format::Format_ARGB32).copy();
|
||||
cursor.hotSpot = QPoint(static_cast<int>(imgXhot), static_cast<int>(imgYhot));
|
||||
|
||||
QString key = QStringLiteral("%1").arg(static_cast<int>(subtype), 3, 10, QLatin1Char('0'));
|
||||
cursorFile.cursorMap.insertMulti(key, cursor);
|
||||
|
||||
file.seek(tocPos);
|
||||
}
|
||||
}
|
||||
|
||||
_cursorFileList << cursorFile;
|
||||
}
|
||||
|
||||
ui->lwCursors->clear();
|
||||
|
||||
QStringList nameList;
|
||||
|
||||
for (const CursorFile &cursorFile: _cursorFileList) {
|
||||
nameList << cursorFile.name;
|
||||
}
|
||||
|
||||
ui->lwCursors->addItems(nameList);
|
||||
}
|
||||
|
||||
void Dialog::showCursor(const QString &fileName)
|
||||
{
|
||||
CursorFile foundCursorFile;
|
||||
|
||||
for (const CursorFile &cursorFile: _cursorFileList) {
|
||||
if (cursorFile.name == fileName) {
|
||||
foundCursorFile = cursorFile;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if(foundCursorFile.name.isEmpty()) {
|
||||
ui->teCursorInfo->clear();
|
||||
return;
|
||||
}
|
||||
|
||||
QString msg = "<html><body>";
|
||||
|
||||
QStringList keys = foundCursorFile.cursorMap.keys();
|
||||
keys.removeDuplicates();
|
||||
keys.sort();
|
||||
|
||||
for (const QString &key: keys) {
|
||||
QList<Cursor> cursorList = foundCursorFile.cursorMap.values(key);
|
||||
msg += "<p>";
|
||||
for (const Cursor &cursor: cursorList) {
|
||||
QByteArray imgBa;
|
||||
QBuffer buffer(&imgBa);
|
||||
cursor.image.save(&buffer, "PNG");
|
||||
|
||||
imgBa = imgBa.toBase64();
|
||||
|
||||
msg += "<img src=\"data:image/png;base64, " + QString::fromLatin1(imgBa) + "\"/>";
|
||||
}
|
||||
msg += "</p>";
|
||||
}
|
||||
|
||||
msg += "</body></html>";
|
||||
|
||||
ui->teCursorInfo->setHtml(msg);
|
||||
}
|
|
@ -0,0 +1,57 @@
|
|||
/*
|
||||
* Copyright (C) 2019 Ivan Romanov <drizt72@zoho.eu>
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <QDialog>
|
||||
|
||||
#include <QImage>
|
||||
#include <QList>
|
||||
#include <QMap>
|
||||
#include <QString>
|
||||
|
||||
namespace Ui { class Dialog; }
|
||||
|
||||
struct Cursor
|
||||
{
|
||||
QImage image;
|
||||
QPoint hotSpot;
|
||||
};
|
||||
|
||||
struct CursorFile
|
||||
{
|
||||
QString name;
|
||||
QMap<QString, Cursor> cursorMap;
|
||||
};
|
||||
|
||||
class Dialog : public QDialog
|
||||
{
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
explicit Dialog(QWidget *parent = nullptr);
|
||||
~Dialog();
|
||||
|
||||
void openFolder();
|
||||
void showCursor(const QString &fileName);
|
||||
|
||||
private:
|
||||
Ui::Dialog *ui;
|
||||
QList<CursorFile> _cursorFileList;
|
||||
};
|
||||
|
|
@ -0,0 +1,78 @@
|
|||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<ui version="4.0">
|
||||
<class>Dialog</class>
|
||||
<widget class="QDialog" name="Dialog">
|
||||
<property name="geometry">
|
||||
<rect>
|
||||
<x>0</x>
|
||||
<y>0</y>
|
||||
<width>513</width>
|
||||
<height>425</height>
|
||||
</rect>
|
||||
</property>
|
||||
<property name="windowTitle">
|
||||
<string>Xcursor Viewer</string>
|
||||
</property>
|
||||
<layout class="QVBoxLayout" name="verticalLayout">
|
||||
<item>
|
||||
<widget class="QWidget" name="widget" native="true">
|
||||
<layout class="QHBoxLayout" name="horizontalLayout">
|
||||
<property name="leftMargin">
|
||||
<number>0</number>
|
||||
</property>
|
||||
<property name="topMargin">
|
||||
<number>0</number>
|
||||
</property>
|
||||
<property name="rightMargin">
|
||||
<number>0</number>
|
||||
</property>
|
||||
<property name="bottomMargin">
|
||||
<number>0</number>
|
||||
</property>
|
||||
<item>
|
||||
<widget class="QPushButton" name="pbOpenFolder">
|
||||
<property name="text">
|
||||
<string>Open folder</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<spacer name="horizontalSpacer">
|
||||
<property name="orientation">
|
||||
<enum>Qt::Horizontal</enum>
|
||||
</property>
|
||||
<property name="sizeHint" stdset="0">
|
||||
<size>
|
||||
<width>40</width>
|
||||
<height>20</height>
|
||||
</size>
|
||||
</property>
|
||||
</spacer>
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QSplitter" name="splitter">
|
||||
<property name="sizePolicy">
|
||||
<sizepolicy hsizetype="Expanding" vsizetype="Expanding">
|
||||
<horstretch>0</horstretch>
|
||||
<verstretch>0</verstretch>
|
||||
</sizepolicy>
|
||||
</property>
|
||||
<property name="orientation">
|
||||
<enum>Qt::Horizontal</enum>
|
||||
</property>
|
||||
<widget class="QListWidget" name="lwCursors"/>
|
||||
<widget class="QTextEdit" name="teCursorInfo">
|
||||
<property name="readOnly">
|
||||
<bool>true</bool>
|
||||
</property>
|
||||
</widget>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
<resources/>
|
||||
<connections/>
|
||||
</ui>
|
|
@ -0,0 +1,32 @@
|
|||
/*
|
||||
* Copyright (C) 2019 Ivan Romanov <drizt72@zoho.eu>
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
*/
|
||||
|
||||
#include "dialog.h"
|
||||
|
||||
#include <QApplication>
|
||||
|
||||
int main(int argc, char *argv[])
|
||||
{
|
||||
QApplication app(argc, argv);
|
||||
|
||||
Dialog dlg;
|
||||
dlg.show();
|
||||
app.exec();
|
||||
|
||||
return 0;
|
||||
}
|
Loading…
Reference in New Issue