Skip to content
Snippets Groups Projects
Commit dc4c5070 authored by akiraohgaki's avatar akiraohgaki Committed by GitHub
Browse files

Merge pull request #24 from xdgurl/development

Development
parents 719d8261 241f7425
No related branches found
No related tags found
No related merge requests found
Showing with 912 additions and 377 deletions
.pragma library
function convertByteToHumanReadable(bytes) {
bytes = parseFloat(bytes);
var kb = 1024;
var mb = 1024 * kb;
var gb = 1024 * mb;
var tb = 1024 * gb;
var pb = 1024 * tb;
var eb = 1024 * pb;
var zb = 1024 * eb;
var yb = 1024 * zb;
var text = '';
if (bytes < kb) {
text = bytes.toFixed(0) + ' B';
}
else if (bytes < mb) {
text = (bytes / kb).toFixed(2) + ' KB';
}
else if (bytes < gb) {
text = (bytes / mb).toFixed(2) + ' MB';
}
else if (bytes < tb) {
text = (bytes / gb).toFixed(2) + ' GB';
}
else if (bytes < pb) {
text = (bytes / tb).toFixed(2) + ' TB';
}
else if (bytes < eb) {
text = (bytes / pb).toFixed(2) + ' PB';
}
else if (bytes < zb) {
text = (bytes / eb).toFixed(2) + ' EB';
}
else if (bytes < yb) {
text = (bytes / zb).toFixed(2) + ' ZB';
}
else if (bytes >= yb) {
text = (bytes / yb).toFixed(2) + ' YB';
}
return text;
}
<RCC>
<qresource prefix="/desktop">
<file>xdgurl.svg</file>
</qresource>
</RCC>
[Desktop Entry]
Name=xdgurl
Exec=xdgurl %u
Icon=xdgurl
Type=Application
Terminal=false
NoDisplay=true
......
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<svg
xmlns:dc="http://purl.org/dc/elements/1.1/"
xmlns:cc="http://creativecommons.org/ns#"
xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
xmlns:svg="http://www.w3.org/2000/svg"
xmlns="http://www.w3.org/2000/svg"
version="1.1"
id="svg2"
viewBox="0 0 1000 1000"
height="1000"
width="1000">
<defs
id="defs4" />
<metadata
id="metadata7">
<rdf:RDF>
<cc:Work
rdf:about="">
<dc:format>image/svg+xml</dc:format>
<dc:type
rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
<dc:title></dc:title>
</cc:Work>
</rdf:RDF>
</metadata>
<g
transform="translate(0,-52.362161)"
id="layer1">
<circle
r="475"
cy="552.36218"
cx="500"
id="path4138"
style="fill:#19a2ff;fill-opacity:1;stroke:none;stroke-width:1;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1" />
<circle
r="450"
cy="552.36218"
cx="500"
id="path4138-0"
style="fill:#53b2ff;fill-opacity:1;stroke:none;stroke-width:1;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1" />
<g
transform="translate(0,20)"
id="g4205">
<path
id="path4145"
style="font-style:normal;font-variant:normal;font-weight:500;font-stretch:normal;font-size:medium;line-height:125%;font-family:Futura;-inkscape-font-specification:'Futura Medium';letter-spacing:0px;word-spacing:0px;fill:#ffffff;fill-opacity:1;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"
d="m 192.87313,533.47911 -74.36008,-101.11803 56.93857,0 46.10326,64.24502 46.95309,-64.24502 58.63824,0 -76.48467,101.11803 88.59474,119.21524 -56.93858,0 -60.76282,-82.34221 -62.25002,82.34221 -58.42577,0 91.99404,-119.21524 z" />
<path
id="path4147"
style="font-style:normal;font-variant:normal;font-weight:500;font-stretch:normal;font-size:medium;line-height:125%;font-family:Futura;-inkscape-font-specification:'Futura Medium';letter-spacing:0px;word-spacing:0px;fill:#ffffff;fill-opacity:1;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"
d="m 472.62967,312.47491 48.01537,0 0,340.84056 -48.01537,0 0,-21.67066 c -18.83789,18.41297 -40.15445,27.61946 -63.94968,27.61946 -28.32765,0 -51.83961,-10.33959 -70.53586,-31.01878 -18.55461,-21.1041 -27.83192,-47.44882 -27.83192,-79.03415 0,-30.87715 9.27731,-56.65531 27.83192,-77.3345 18.41298,-20.82082 41.57084,-31.23123 69.47357,-31.23123 24.22015,0 45.8908,9.91468 65.01197,29.74403 z M 359.17742,549.21134 c 0,19.82935 5.31143,35.97612 15.9343,48.44029 10.90615,12.60581 24.64506,18.90871 41.21674,18.90871 17.70478,0 32.01024,-6.09045 42.91639,-18.27134 10.90615,-12.60581 16.35922,-28.61093 16.35922,-48.01537 0,-19.40445 -5.45307,-35.40957 -16.35922,-48.01538 -10.90615,-12.32253 -25.06997,-18.48379 -42.49148,-18.48379 -16.43004,0 -30.16895,6.23208 -41.21673,18.69625 -10.90615,12.60581 -16.35922,28.18602 -16.35922,46.74063 z" />
<path
id="path4149"
style="font-style:normal;font-variant:normal;font-weight:500;font-stretch:normal;font-size:medium;line-height:125%;font-family:Futura;-inkscape-font-specification:'Futura Medium';letter-spacing:0px;word-spacing:0px;fill:#ffffff;fill-opacity:1;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"
d="m 722.24998,648.95295 c 0,9.77304 -0.3541,18.34215 -1.06229,25.70734 -0.56655,7.50683 -1.41638,14.09301 -2.54949,19.75854 -3.39932,15.58021 -10.05632,28.96502 -19.97099,40.15445 -18.69625,21.52901 -44.4036,32.29352 -77.12204,32.29352 -27.61947,0 -50.35241,-7.43601 -68.19883,-22.30802 -18.41297,-15.29693 -29.03584,-36.47186 -31.86861,-63.52477 l 48.01537,0 c 1.8413,10.19796 4.88652,18.05889 9.13567,23.58278 9.91468,12.88908 24.36178,19.33362 43.34131,19.33362 34.98465,0 52.47698,-21.4582 52.47698,-64.37459 l 0,-28.89421 c -18.97953,19.40444 -40.86264,29.10666 -65.64934,29.10666 -28.18601,0 -51.27305,-10.19795 -69.26111,-30.59386 -18.1297,-20.67919 -27.19455,-46.52817 -27.19455,-77.54695 0,-30.16895 8.42748,-55.80548 25.28243,-76.90959 18.1297,-22.37884 42.06657,-33.56826 71.81061,-33.56826 26.06144,0 47.73209,9.70222 65.01196,29.10666 l 0,-27.37031 47.80292,0 z m -45.8908,-98.15532 c 0,-20.11264 -5.38225,-36.18859 -16.14676,-48.22784 C 649.30627,490.24726 635.3549,484.086 618.35831,484.086 c -18.1297,0 -32.43517,6.72782 -42.9164,20.18345 -9.48976,12.03925 -14.23464,27.61946 -14.23464,46.74063 0,18.83789 4.74488,34.27647 14.23464,46.31572 10.33959,13.17236 24.64506,19.75854 42.9164,19.75854 18.27133,0 32.71844,-6.657 43.34131,-19.971 9.77304,-12.03925 14.65956,-27.47782 14.65956,-46.31571 z" />
<path
style="fill:#ffffff;fill-opacity:1;stroke:none;stroke-width:1;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
d="m 739.50519,490.21255 36,0 0,36 -36,0 z"
id="rect4156" />
<path
style="fill:#ffffff;fill-opacity:1;stroke:none;stroke-width:1;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
d="m 739.53345,589.21057 36,0 0,36 -36,0 z"
id="rect4156-9" />
<path
style="fill:#ffffff;fill-opacity:1;stroke:none;stroke-width:1;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
d="m 852.99238,412.46896 22,0 -94.33913,290.17369 -22,0 z"
id="rect4156-5" />
<path
style="fill:#ffffff;fill-opacity:1;stroke:none;stroke-width:1;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
d="m 902.99238,412.46896 22,0 -94.33913,290.17369 -22,0 z"
id="rect4156-5-3" />
</g>
</g>
</svg>
/**
* A library for Qt app
*
* LICENSE: The GNU Lesser General Public License, version 3.0
*
* @author Akira Ohgaki <akiraohgaki@gmail.com>
* @copyright Akira Ohgaki
* @license https://opensource.org/licenses/LGPL-3.0 The GNU Lesser General Public License, version 3.0
* @link https://github.com/akiraohgaki/qt-libs
*/
#include "android.h"
#include <QAndroidJniObject>
namespace utils {
Android::Android(QObject *parent) : QObject(parent)
{}
bool Android::openApk(const QString &uri)
{
QAndroidJniObject activity = QAndroidJniObject::callStaticObjectMethod("org/qtproject/qt5/android/QtNative", "activity", "()Landroid/app/Activity;");
if (activity.isValid()) {
QAndroidJniObject fileUri = QAndroidJniObject::fromString(uri);
QAndroidJniObject parsedUri = QAndroidJniObject::callStaticObjectMethod("android/net/Uri", "parse", "(Ljava/lang/String;)Landroid/net/Uri;", fileUri.object());
QAndroidJniObject mimeType = QAndroidJniObject::fromString("application/vnd.android.package-archive");
QAndroidJniObject activityKind = QAndroidJniObject::fromString("android.intent.action.VIEW");
QAndroidJniObject intent("android/content/Intent", "(Ljava/lang/String;)V", activityKind.object());
intent = intent.callObjectMethod("setDataAndType", "(Landroid/net/Uri;Ljava/lang/String;)Landroid/content/Intent;", parsedUri.object(), mimeType.object());
intent = intent.callObjectMethod("setFlags", "(I)Landroid/content/Intent;", 0x10000000); // 0x10000000 = FLAG_ACTIVITY_NEW_TASK
activity.callObjectMethod("startActivity", "(Landroid/content/Intent;)V", intent.object());
return true;
}
return false;
}
} // namespace utils
/**
* A library for Qt app
*
* LICENSE: The GNU Lesser General Public License, version 3.0
*
* @author Akira Ohgaki <akiraohgaki@gmail.com>
* @copyright Akira Ohgaki
* @license https://opensource.org/licenses/LGPL-3.0 The GNU Lesser General Public License, version 3.0
* @link https://github.com/akiraohgaki/qt-libs
*/
#pragma once
#include <QObject>
namespace utils {
class Android : public QObject
{
Q_OBJECT
public:
explicit Android(QObject *parent = 0);
static bool openApk(const QString &uri);
};
} // namespace utils
/**
* A library for Qt app
*
* LICENSE: The GNU Lesser General Public License, version 3.0
*
* @author Akira Ohgaki <akiraohgaki@gmail.com>
* @copyright Akira Ohgaki
* @license https://opensource.org/licenses/LGPL-3.0 The GNU Lesser General Public License, version 3.0
* @link https://github.com/akiraohgaki/qt-libs
*/
#include "config.h"
#include "file.h"
#include "json.h"
namespace utils {
Config::Config(const QString &configsDir, QObject *parent) :
QObject(parent), configsDir_(configsDir)
{}
QJsonObject Config::get(const QString &name)
{
QString configFile = configsDir_ + "/" + name + ".json";
if (!cacheData_.contains(name)) {
QString json = utils::File::readText(configFile);
if (json.isEmpty()) {
json = "{}"; // Blank JSON data as default
}
cacheData_[name] = utils::Json::convertStrToObj(json);
}
return cacheData_[name].toObject();
}
bool Config::set(const QString &name, const QJsonObject &jsonObj)
{
QString configFile = configsDir_ + "/" + name + ".json";
QString json = utils::Json::convertObjToStr(jsonObj);
utils::File::makeDir(configsDir_);
if (utils::File::writeText(configFile, json)) {
cacheData_[name] = jsonObj;
return true;
}
return false;
}
} // namespace utils
/**
* A library for Qt app
*
* LICENSE: The GNU Lesser General Public License, version 3.0
*
* @author Akira Ohgaki <akiraohgaki@gmail.com>
* @copyright Akira Ohgaki
* @license https://opensource.org/licenses/LGPL-3.0 The GNU Lesser General Public License, version 3.0
* @link https://github.com/akiraohgaki/qt-libs
*/
#pragma once
#include <QObject>
#include <QJsonObject>
namespace utils {
class Config : public QObject
{
Q_OBJECT
public:
explicit Config(const QString &configsDir, QObject *parent = 0);
QJsonObject get(const QString &name);
bool set(const QString &name, const QJsonObject &jsonObj);
private:
QString configsDir_;
QJsonObject cacheData_;
};
} // namespace utils
/**
* A library for Qt app
*
* LICENSE: The GNU Lesser General Public License, version 3.0
*
* @author Akira Ohgaki <akiraohgaki@gmail.com>
* @copyright Akira Ohgaki
* @license https://opensource.org/licenses/LGPL-3.0 The GNU Lesser General Public License, version 3.0
* @link https://github.com/akiraohgaki/qt-libs
*/
#include "file.h"
#include <QIODevice>
#include <QStandardPaths>
#include <QDir>
#include <QFile>
#include <QFileInfo>
#include <QTextStream>
namespace utils {
File::File(QObject *parent) : QObject(parent)
{}
QString File::rootPath()
{
return QDir::rootPath();
}
QString File::tempPath()
{
return QDir::tempPath();
}
QString File::homePath()
{
return QDir::homePath();
}
QString File::genericDataPath()
{
return QStandardPaths::writableLocation(QStandardPaths::GenericDataLocation);
}
QString File::genericConfigPath()
{
return QStandardPaths::writableLocation(QStandardPaths::GenericConfigLocation);
}
QString File::genericCachePath()
{
return QStandardPaths::writableLocation(QStandardPaths::GenericCacheLocation);
}
QString File::kdehomePath()
{
// KDE System Administration/Environment Variables
// https://userbase.kde.org/KDE_System_Administration/Environment_Variables
// KDE 4 maybe uses $KDEHOME
QString path = QString::fromLocal8Bit(qgetenv("KDEHOME").constData());
if (path.isEmpty()) {
path = homePath() + "/.kde";
}
return path;
}
QFileInfoList File::readDir(const QString &path)
{
QDir dir(path);
dir.setFilter(QDir::AllEntries | QDir::Hidden | QDir::System | QDir::NoDotAndDotDot);
//dir.setSorting(QDir::DirsFirst | QDir::Name);
return dir.entryInfoList();
}
bool File::makeDir(const QString &path)
{
// This function will create all parent directories
QDir dir(path);
if (!dir.exists() && dir.mkpath(path)) {
return true;
}
return false;
}
QString File::readText(const QString &path)
{
QString data;
QFile file(path);
if (file.exists() && file.open(QIODevice::ReadOnly | QIODevice::Text)) {
QTextStream in(&file);
in.setCodec("UTF-8");
data = in.readAll();
file.close();
}
return data;
}
bool File::writeText(const QString &path, const QString &data)
{
QFile file(path);
if (file.open(QIODevice::WriteOnly | QIODevice::Text)) {
QTextStream out(&file);
out.setCodec("UTF-8");
out << data;
file.close();
return true;
}
return false;
}
QByteArray File::readBinary(const QString &path)
{
QByteArray data;
QFile file(path);
if (file.exists() && file.open(QIODevice::ReadOnly)) {
data = file.readAll();
file.close();
}
return data;
}
bool File::writeBinary(const QString &path, const QByteArray &data)
{
QFile file(path);
if (file.open(QIODevice::WriteOnly)) {
file.write(data);
file.close();
return true;
}
return false;
}
bool File::copy(const QString &path, const QString &targetPath)
{
// This function will copy files recursively
QFileInfo fileInfo(path);
if (fileInfo.isFile()) {
QFile file(path);
if (file.copy(targetPath)) {
return true;
}
}
else if (fileInfo.isDir()) {
QDir targetDir(targetPath);
QString targetDirName = targetDir.dirName();
targetDir.cdUp();
if (targetDir.mkdir(targetDirName)) {
QDir dir(path);
dir.setFilter(QDir::AllEntries | QDir::Hidden | QDir::System | QDir::NoDotAndDotDot);
QStringList entries = dir.entryList();
foreach (const QString &entry, entries) {
if (!copy(path + "/" + entry, targetPath + "/" + entry)) {
return false;
}
}
return true;
}
}
return false;
}
bool File::move(const QString &path, const QString &targetPath)
{
QFileInfo fileInfo(path);
if (fileInfo.isFile()) {
QFile file(path);
if (file.rename(targetPath)) {
return true;
}
}
else if (fileInfo.isDir()) {
QDir dir(path);
if (dir.rename(path, targetPath)) {
return true;
}
}
return false;
}
bool File::remove(const QString &path)
{
// This function will remove files recursively
QFileInfo fileInfo(path);
if (fileInfo.isFile()) {
QFile file(path);
if (file.remove()) {
return true;
}
}
else if (fileInfo.isDir()) {
QDir dir(path);
if (dir.removeRecursively()) {
return true;
}
}
return false;
}
} // namespace utils
/**
* A library for Qt app
*
* LICENSE: The GNU Lesser General Public License, version 3.0
*
* @author Akira Ohgaki <akiraohgaki@gmail.com>
* @copyright Akira Ohgaki
* @license https://opensource.org/licenses/LGPL-3.0 The GNU Lesser General Public License, version 3.0
* @link https://github.com/akiraohgaki/qt-libs
*/
#pragma once
#include <QObject>
class QFileInfo;
typedef QList<QFileInfo> QFileInfoList;
namespace utils {
class File : public QObject
{
Q_OBJECT
public:
explicit File(QObject *parent = 0);
static QString rootPath();
static QString tempPath();
static QString homePath();
static QString genericDataPath();
static QString genericConfigPath();
static QString genericCachePath();
static QString kdehomePath();
static QFileInfoList readDir(const QString &path);
static bool makeDir(const QString &path);
static QString readText(const QString &path);
static bool writeText(const QString &path, const QString &data);
static QByteArray readBinary(const QString &path);
static bool writeBinary(const QString &path, const QByteArray &data);
static bool copy(const QString &path, const QString &targetPath);
static bool move(const QString &path, const QString &targetPath);
static bool remove(const QString &path);
};
} // namespace utils
/**
* A library for Qt app
*
* LICENSE: The GNU Lesser General Public License, version 3.0
*
* @author Akira Ohgaki <akiraohgaki@gmail.com>
* @copyright Akira Ohgaki
* @license https://opensource.org/licenses/LGPL-3.0 The GNU Lesser General Public License, version 3.0
* @link https://github.com/akiraohgaki/qt-libs
*/
#include "json.h"
#include <QJsonDocument>
#include <QJsonObject>
#include <QJsonParseError>
namespace utils {
Json::Json(QObject *parent) : QObject(parent)
{}
QString Json::convertObjToStr(const QJsonObject &jsonObj)
{
QJsonDocument jsonDoc(jsonObj);
return QString::fromUtf8(jsonDoc.toJson());
}
QJsonObject Json::convertStrToObj(const QString &json)
{
QJsonObject jsonObj;
QJsonParseError jsonError;
QJsonDocument jsonDoc = QJsonDocument::fromJson(json.toUtf8(), &jsonError);
if (jsonError.error == QJsonParseError::NoError && jsonDoc.isObject()) {
jsonObj = jsonDoc.object();
}
return jsonObj;
}
bool Json::isValid(const QString &json)
{
QJsonParseError jsonError;
QJsonDocument::fromJson(json.toUtf8(), &jsonError);
if (jsonError.error == QJsonParseError::NoError) {
return true;
}
return false;
}
} // namespace utils
/**
* A library for Qt app
*
* LICENSE: The GNU Lesser General Public License, version 3.0
*
* @author Akira Ohgaki <akiraohgaki@gmail.com>
* @copyright Akira Ohgaki
* @license https://opensource.org/licenses/LGPL-3.0 The GNU Lesser General Public License, version 3.0
* @link https://github.com/akiraohgaki/qt-libs
*/
#pragma once
#include <QObject>
namespace utils {
class Json : public QObject
{
Q_OBJECT
public:
explicit Json(QObject *parent = 0);
static QString convertObjToStr(const QJsonObject &jsonObj);
static QJsonObject convertStrToObj(const QString &json);
static bool isValid(const QString &json);
};
} // namespace utils
/**
* A library for Qt app
*
* LICENSE: The GNU Lesser General Public License, version 3.0
*
* @author Akira Ohgaki <akiraohgaki@gmail.com>
* @copyright Akira Ohgaki
* @license https://opensource.org/licenses/LGPL-3.0 The GNU Lesser General Public License, version 3.0
* @link https://github.com/akiraohgaki/qt-libs
*/
#include "network.h"
#include <QEventLoop>
#include <QNetworkAccessManager>
#include <QNetworkRequest>
#include <QNetworkReply>
namespace utils {
Network::Network(const bool &async, QObject *parent) :
QObject(parent), async_(async)
{
manager_ = new QNetworkAccessManager(this);
connect(manager_, &QNetworkAccessManager::finished, this, &utils::Network::finished);
if (!async_) {
eventLoop_ = new QEventLoop();
connect(manager_, &QNetworkAccessManager::finished, eventLoop_, &QEventLoop::quit);
}
}
Network::~Network()
{
manager_->deleteLater();
if (!async_) {
delete eventLoop_;
}
}
QNetworkReply *Network::head(const QUrl &uri)
{
QNetworkReply *reply = manager_->head(QNetworkRequest(uri));
if (!async_) {
eventLoop_->exec();
}
return reply;
}
QNetworkReply *Network::get(const QUrl &uri)
{
QNetworkReply *reply = manager_->get(QNetworkRequest(uri));
connect(reply, &QNetworkReply::downloadProgress, this, &utils::Network::downloadProgress);
if (!async_) {
eventLoop_->exec();
}
return reply;
}
} // namespace utils
/**
* A library for Qt app
*
* LICENSE: The GNU Lesser General Public License, version 3.0
*
* @author Akira Ohgaki <akiraohgaki@gmail.com>
* @copyright Akira Ohgaki
* @license https://opensource.org/licenses/LGPL-3.0 The GNU Lesser General Public License, version 3.0
* @link https://github.com/akiraohgaki/qt-libs
*/
#pragma once
#include <QObject>
class QEventLoop;
class QNetworkAccessManager;
class QNetworkReply;
namespace utils {
class Network : public QObject
{
Q_OBJECT
public:
explicit Network(const bool &async = true, QObject *parent = 0);
~Network();
QNetworkReply *head(const QUrl &uri);
QNetworkReply *get(const QUrl &uri);
signals:
void finished(QNetworkReply *reply);
void downloadProgress(const qint64 &received, const qint64 &total);
private:
bool async_;
QNetworkAccessManager *manager_;
QEventLoop *eventLoop_;
};
} // namespace utils
/**
* A library for Qt app
*
* LICENSE: The GNU Lesser General Public License, version 3.0
*
* @author Akira Ohgaki <akiraohgaki@gmail.com>
* @copyright Akira Ohgaki
* @license https://opensource.org/licenses/LGPL-3.0 The GNU Lesser General Public License, version 3.0
* @link https://github.com/akiraohgaki/qt-libs
*/
#include "package.h"
#include <QJsonObject>
#include <QMimeDatabase>
#include <QProcess>
namespace utils {
Package::Package(QObject *parent) : QObject(parent)
{}
bool Package::installProgram(const QString &path, const QString &targetPath)
{
QString program = "install";
QStringList arguments;
arguments << "-m" << "755" << "-p" << path << targetPath;
return execute(program, arguments);
}
bool Package::installFile(const QString &path, const QString &targetPath)
{
QString program = "install";
QStringList arguments;
arguments << "-m" << "644" << "-p" << path << targetPath;
return execute(program, arguments);
}
bool Package::installPlasmapkg(const QString &path, const QString &type)
{
QString program = "plasmapkg2";
QStringList arguments;
arguments << "-t" << type << "-i" << path;
return execute(program, arguments);
}
bool Package::uninstallPlasmapkg(const QString &path, const QString &type)
{
QString program = "plasmapkg2";
QStringList arguments;
arguments << "-t" << type << "-r" << path;
return execute(program, arguments);
}
bool Package::uncompressArchive(const QString &path, const QString &targetDir)
{
QJsonObject archiveTypes;
archiveTypes["application/x-tar"] = QString("tar");
archiveTypes["application/x-gzip"] = QString("tar");
archiveTypes["application/gzip"] = QString("tar");
archiveTypes["application/x-bzip"] = QString("tar");
archiveTypes["application/x-bzip2"] = QString("tar");
archiveTypes["application/x-xz"] = QString("tar");
archiveTypes["application/x-lzma"] = QString("tar");
archiveTypes["application/x-lzip"] = QString("tar");
archiveTypes["application/x-compressed-tar"] = QString("tar");
archiveTypes["application/x-bzip-compressed-tar"] = QString("tar");
archiveTypes["application/x-bzip2-compressed-tar"] = QString("tar");
archiveTypes["application/x-xz-compressed-tar"] = QString("tar");
archiveTypes["application/x-lzma-compressed-tar"] = QString("tar");
archiveTypes["application/x-lzip-compressed-tar"] = QString("tar");
archiveTypes["application/zip"] = QString("zip");
archiveTypes["application/x-7z-compressed"] = QString("7z");
archiveTypes["application/x-rar"] = QString("rar");
archiveTypes["application/x-rar-compressed"] = QString("rar");
QMimeDatabase mimeDb;
QString mimeType = mimeDb.mimeTypeForFile(path).name();
if (archiveTypes.contains(mimeType)) {
QString archiveType = archiveTypes[mimeType].toString();
QString program;
QStringList arguments;
if (archiveType == "tar") {
program = "tar";
arguments << "-xf" << path << "-C" << targetDir;
}
else if (archiveType == "zip") {
program = "unzip";
arguments << "-o" << path << "-d" << targetDir;
}
else if (archiveType == "7z") {
program = "7z";
arguments << "x" << path << "-o" + targetDir; // No space between -o and directory
}
else if (archiveType == "rar") {
program = "unrar";
arguments << "e" << path << targetDir;
}
return execute(program, arguments);
}
return false;
}
bool Package::execute(const QString &program, const QStringList &arguments)
{
QProcess process;
process.start(program, arguments);
if (process.waitForFinished()) {
process.waitForReadyRead();
return true;
}
return false;
}
} // namespace utils
/**
* A library for Qt app
*
* LICENSE: The GNU Lesser General Public License, version 3.0
*
* @author Akira Ohgaki <akiraohgaki@gmail.com>
* @copyright Akira Ohgaki
* @license https://opensource.org/licenses/LGPL-3.0 The GNU Lesser General Public License, version 3.0
* @link https://github.com/akiraohgaki/qt-libs
*/
#pragma once
#include <QObject>
namespace utils {
class Package : public QObject
{
Q_OBJECT
public:
explicit Package(QObject *parent = 0);
static bool installProgram(const QString &path, const QString &targetPath);
static bool installFile(const QString &path, const QString &targetPath);
static bool installPlasmapkg(const QString &path, const QString &type = "plasmoid");
static bool uninstallPlasmapkg(const QString &path, const QString &type = "plasmoid");
static bool uncompressArchive(const QString &path, const QString &targetDir);
private:
static bool execute(const QString &program, const QStringList &arguments);
};
} // namespace utils
#!/usr/bin/env python
"""xdgurl
An install helper program for desktop stuff.
Copyright: 2016, Akira Ohgaki
License: GPL-3+
https://github.com/xdgurl/xdgurl
"""
import sys
import os
import shutil
import json
import tempfile
import mimetypes
import subprocess
import argparse
if sys.version_info.major >= 3:
import urllib.request
import urllib.error
import urllib.parse
import tkinter
import tkinter.messagebox
else:
import urllib
import urlparse
import Tkinter
import tkMessageBox
class XdgUrl:
def __init__(self, xdg_url=''):
self.xdg_url = xdg_url
self.meta = self.parse()
self.temp_dir = tempfile.gettempdir()
self.home_dir = os.path.expanduser('~')
#self.config_dir = os.path.join(self.home_dir, '.config', 'xdgurl')
self.data_dir = os.path.join(self.home_dir, '.local', 'share')
self.kde_data_dir = os.path.join(self.home_dir, '.kde', 'share')
#self.config = {}
self.destinations = {
'downloads': os.path.join(self.home_dir, 'Downloads'),
'documents': os.path.join(self.home_dir, 'Documents'),
'pictures': os.path.join(self.home_dir, 'Pictures'),
'music': os.path.join(self.home_dir, 'Music'),
'videos': os.path.join(self.home_dir, 'Videos'),
'wallpapers': os.path.join(self.data_dir, 'wallpapers'),
'fonts': os.path.join(self.home_dir, '.fonts'),
'cursors': os.path.join(self.home_dir, '.icons'),
'icons': os.path.join(self.data_dir, 'icons'),
'emoticons': os.path.join(self.data_dir, 'emoticons'),
'themes': os.path.join(self.home_dir, '.themes'),
'emerald_themes': os.path.join(self.home_dir, '.emerald', 'themes'),
'enlightenment_themes': os.path.join(self.home_dir, '.e', 'e', 'themes'),
'enlightenment_backgrounds': os.path.join(self.home_dir, '.e', 'e', 'backgrounds'),
'fluxbox_styles': os.path.join(self.home_dir, '.fluxbox', 'styles'),
'pekwm_themes': os.path.join(self.home_dir, '.pekwm', 'themes'),
'icewm_themes': os.path.join(self.home_dir, '.icewm', 'themes'),
'plasma_plasmoids': os.path.join(self.data_dir, 'plasma', 'plasmoids'),
'plasma_look_and_feel': os.path.join(self.data_dir, 'plasma', 'look-and-feel'),
'plasma_desktopthemes': os.path.join(self.data_dir, 'plasma', 'desktoptheme'),
'kwin_effects': os.path.join(self.data_dir, 'kwin', 'effects'),
'kwin_scripts': os.path.join(self.data_dir, 'kwin', 'scripts'),
'kwin_tabbox': os.path.join(self.data_dir, 'kwin', 'tabbox'),
'aurorae_themes': os.path.join(self.data_dir, 'aurorae', 'themes'),
'dekorator_themes': os.path.join(self.data_dir, 'deKorator', 'themes'),
'qtcurve': os.path.join(self.data_dir, 'QtCurve'),
'color_schemes': os.path.join(self.data_dir, 'color-schemes'),
'gnome_shell_extensions': os.path.join(self.data_dir, 'gnome-shell', 'extensions'),
'cinnamon_applets': os.path.join(self.data_dir, 'cinnamon', 'applets'),
'cinnamon_desklets': os.path.join(self.data_dir, 'cinnamon', 'desklets'),
'cinnamon_extensions': os.path.join(self.data_dir, 'cinnamon', 'extensions'),
'nautilus_scripts': os.path.join(self.data_dir, 'nautilus', 'scripts'),
'amarok_scripts': os.path.join(self.kde_data_dir, 'apps', 'amarok', 'scripts'),
'yakuake_skins': os.path.join(self.kde_data_dir, 'apps', 'yakuake', 'skins'),
'cairo_clock_themes': os.path.join(self.home_dir, '.cairo-clock', 'themes')
}
self.destinations_alias = {
'gnome_shell_themes': self.destinations['themes'],
'cinnamon_themes': self.destinations['themes'],
'gtk2_themes': self.destinations['themes'],
'gtk3_themes': self.destinations['themes'],
'metacity_themes': self.destinations['themes'],
'xfwm4_themes': self.destinations['themes'],
'openbox_themes': self.destinations['themes'],
'kvantum_themes': self.destinations['themes'],
'compiz_themes': self.destinations['emerald_themes'],
'beryl_themes': self.destinations['emerald_themes'],
'plasma4_plasmoids': self.destinations['plasma_plasmoids'],
'plasma5_plasmoids': self.destinations['plasma_plasmoids'],
'plasma5_look_and_feel': self.destinations['plasma_look_and_feel'],
'plasma5_desktopthemes': self.destinations['plasma_desktopthemes'],
'plasma_color_schemes': self.destinations['color_schemes']
}
self.destinations.update(self.destinations_alias)
self.archive_types = {
'tar': [
'application/x-tar',
'application/x-gzip',
'application/gzip',
'application/x-bzip',
'application/x-bzip2',
'application/x-xz',
'application/x-lzma',
'application/x-lzip',
'application/x-compressed-tar',
'application/x-bzip-compressed-tar',
'application/x-bzip2-compressed-tar',
'application/x-xz-compressed-tar',
'application/x-lzma-compressed-tar',
'application/x-lzip-compressed-tar'
],
'zip': ['application/zip'],
'7z': ['application/x-7z-compressed'],
'rar': [
'application/x-rar',
'application/x-rar-compressed'
]
}
#self.config.update(self.read_config('config'))
#self.destinations.update(self.read_config('destinations'))
def read_config(self, name):
path = os.path.join(self.config_dir, name + '.json')
data = {}
if os.path.isfile(path):
f = open(path, 'r')
data = json.load(f)
f.close()
return data
def write_config(self, name, data):
if not os.path.isdir(self.config_dir):
os.makedirs(self.config_dir)
path = os.path.join(self.config_dir, name + '.json')
f = open(path, 'w')
json.dump(data, f)
f.close()
def parse(self):
meta = {
'command': 'download',
'url': '',
'type': 'downloads',
'filename': ''
}
if sys.version_info.major >= 3:
parse_result = urllib.parse.urlparse(self.xdg_url)
query = urllib.parse.parse_qs(parse_result.query)
else:
parse_result = urlparse.urlparse(self.xdg_url)
query = urlparse.parse_qs(parse_result.query)
if parse_result.netloc:
meta['command'] = parse_result.netloc
if 'url' in query and query['url'][0]:
if sys.version_info.major >= 3:
meta['url'] = urllib.parse.unquote(query['url'][0])
else:
meta['url'] = urllib.unquote(query['url'][0])
if 'type' in query and query['type'][0]:
if sys.version_info.major >= 3:
meta['type'] = urllib.parse.unquote(query['type'][0])
else:
meta['type'] = urllib.unquote(query['type'][0])
if 'filename' in query and query['filename'][0]:
if sys.version_info.major >= 3:
meta['filename'] = urllib.parse.unquote(query['filename'][0]).split('?')[0]
else:
meta['filename'] = urllib.unquote(query['filename'][0]).split('?')[0]
if meta['url'] and not meta['filename']:
meta['filename'] = os.path.basename(meta['url']).split('?')[0]
return meta
"""
def detect_desktop_environment(self):
desktop_environment = 'unknown'
if os.environ.get('KDE_FULL_SESSION') == 'true':
desktop_environment = 'kde'
elif os.environ.get('GNOME_DESKTOP_SESSION_ID'):
desktop_environment = 'gnome'
return desktop_environment
"""
def install_plasmapkg(self, path, type='plasmoid'):
status = subprocess.call(['plasmapkg2', '-t', type, '-i', path])
if status == 0:
return True
return False
def uncompress_archive(self, path, target_dir):
(mimetype, encoding) = mimetypes.guess_type(path)
status = None
if mimetype in self.archive_types['tar']:
status = subprocess.call(['tar', '-xf', path, '-C', target_dir])
elif mimetype in self.archive_types['zip']:
status = subprocess.call(['unzip', '-o', path, '-d', target_dir])
elif mimetype in self.archive_types['7z']:
# No space between -o and directory
status = subprocess.call(['7z', 'x', path, '-o' + target_dir])
elif mimetype in self.archive_types['rar']:
status = subprocess.call(['unrar', 'e', path, target_dir])
if status == 0:
return True
return False
def download(self):
url = self.meta['url']
type = self.meta['type']
filename = self.meta['filename']
destination = self.destinations[type]
temp_path = os.path.join(self.temp_dir, filename)
path = os.path.join(destination, filename)
print('Retrieving a file from ' + url)
if sys.version_info.major >= 3:
urllib.request.urlretrieve(url, temp_path)
else:
urllib.urlretrieve(url, temp_path)
print('Creating a directory ' + destination)
if not os.path.isdir(destination):
os.makedirs(destination)
print('Saving a file to ' + path)
shutil.move(temp_path, path)
print('Done')
def install(self):
url = self.meta['url']
type = self.meta['type']
filename = self.meta['filename']
destination = self.destinations[type]
temp_path = os.path.join(self.temp_dir, filename)
path = os.path.join(destination, filename)
print('Retrieving a file from ' + url)
if sys.version_info.major >= 3:
urllib.request.urlretrieve(url, temp_path)
else:
urllib.urlretrieve(url, temp_path)
print('Creating a directory ' + destination)
if not os.path.isdir(destination):
os.makedirs(destination)
print('Installing')
if (type in ['plasma_plasmoids', 'plasma4_plasmoids', 'plasma5_plasmoids']
and self.install_plasmapkg(temp_path, 'plasmoid')):
print('The plasmoid has been installed')
os.remove(temp_path)
elif (type in ['plasma_look_and_feel', 'plasma5_look_and_feel']
and self.install_plasmapkg(temp_path, 'lookandfeel')):
print('The plasma look and feel has been installed')
os.remove(temp_path)
elif (type in ['plasma_desktopthemes', 'plasma5_desktopthemes']
and self.install_plasmapkg(temp_path, 'theme')):
print('The plasma desktop theme has been installed')
os.remove(temp_path)
elif (type == 'kwin_effects'
and self.install_plasmapkg(temp_path, 'kwineffect')):
print('The KWin effect has been installed')
os.remove(temp_path)
elif (type == 'kwin_scripts'
and self.install_plasmapkg(temp_path, 'kwinscript')):
print('The KWin script has been installed')
os.remove(temp_path)
elif (type == 'kwin_tabbox'
and self.install_plasmapkg(temp_path, 'windowswitcher')):
print('The KWin window switcher has been installed')
os.remove(temp_path)
elif self.uncompress_archive(temp_path, destination):
print('The archive file has been uncompressed into ' + destination)
os.remove(temp_path)
else:
print('Saving a file to ' + path)
shutil.move(temp_path, path)
print('Done')
def execute(self):
if (self.meta['command'] in ['download', 'install']
and self.meta['url']
and self.meta['type'] in self.destinations
and self.meta['filename']):
if self.meta['command'] == 'download':
self.download()
elif self.meta['command'] == 'install':
self.install()
else:
raise Exception('Incorrect XDG-URL ' + self.xdg_url)
def main():
program = 'xdgurl'
version = '1.0.1'
parser = argparse.ArgumentParser(
prog=program,
description='An install helper program for desktop stuff',
epilog='Check more information on https://github.com/xdgurl/xdgurl'
)
parser.add_argument(
'-v', '--version',
action='version',
version='%(prog)s ' + version
)
parser.add_argument('xdg_url', help='XDG-URL')
args = parser.parse_args()
if args.xdg_url:
core = XdgUrl(args.xdg_url)
if sys.version_info.major >= 3:
window = tkinter.Tk()
else:
window = Tkinter.Tk()
window.withdraw()
info_text = 'Download: ' + core.meta['filename'] + '\nFrom: ' + core.meta['url']
if core.meta['command'] == 'install':
info_text = 'Install: ' + core.meta['filename'] + '\nFrom: ' + core.meta['url']
message = 'Do you want to continue?'
print(info_text)
if sys.version_info.major >= 3:
confirm = tkinter.messagebox.askyesno(program, info_text + '\n\n' + message)
else:
confirm = tkMessageBox.askyesno(program, info_text + '\n\n' + message)
if confirm:
try:
core.execute();
except Exception as e:
message = 'Download failed'
if core.meta['command'] == 'install':
message = 'Installation failed'
print(message)
if sys.version_info.major >= 3:
tkinter.messagebox.showerror(program, info_text + '\n\n' + message + '\n' + str(e))
else:
tkMessageBox.showerror(program, info_text + '\n\n' + message + '\n' + str(e))
return str(e) # stderr and exit code 1
else:
message = 'Download successfull'
if core.meta['command'] == 'install':
message = 'Installation successfull'
print(message)
if sys.version_info.major >= 3:
tkinter.messagebox.showinfo(program, message)
else:
tkMessageBox.showinfo(program, message)
return 0
if __name__ == '__main__':
sys.exit(main())
TARGET = xdgurl
TEMPLATE = app
QT += \
core \
gui \
widgets \
qml \
quick \
svg \
network
CONFIG += c++11
SOURCES += \
src/app/main.cpp \
src/app/handlers/xdgurl.cpp \
src/libs/utils/config.cpp \
src/libs/utils/network.cpp \
src/libs/utils/file.cpp \
src/libs/utils/json.cpp \
src/libs/utils/package.cpp
HEADERS += \
src/app/handlers/xdgurl.h \
src/libs/utils/config.h \
src/libs/utils/network.h \
src/libs/utils/file.h \
src/libs/utils/json.h \
src/libs/utils/package.h
RESOURCES += \
src/app/configs/configs.qrc \
src/app/qml/qml.qrc \
src/desktop/desktop.qrc
DISTFILES += \
README.md \
pkg/build.sh \
pkg/ubuntu/debian/changelog \
pkg/ubuntu/debian/compat \
pkg/ubuntu/debian/control \
pkg/ubuntu/debian/copyright \
pkg/ubuntu/debian/rules \
pkg/ubuntu/debian/xdgurl.install \
pkg/fedora/xdgurl.spec \
pkg/arch/PKGBUILD
# Additional RPATH
#include(rpath.pri)
# Deployment rules
include(deployment.pri)
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment