stacer native

This commit is contained in:
Oğuzhan İnan
2017-08-23 14:49:45 +03:00
parent 7e2dbef74a
commit 82247ac648
174 changed files with 16422 additions and 0 deletions

4
.gitignore vendored Normal file
View File

@@ -0,0 +1,4 @@
Stacer.pro.user*
dist/
build/
#*.AppImage

21
LICENSE Normal file
View File

@@ -0,0 +1,21 @@
MIT License
Copyright (c) 2017 Oguzhan Inan
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.

133
README.md Normal file
View File

@@ -0,0 +1,133 @@
<p align="center">
<img src="https://raw.githubusercontent.com/oguzhaninan/Stacer/master/Screenshots/Header.png" width="800">
</p>
<p align="center">
<b>Linux System Optimizer and Monitoring</b>
</p>
<p align="center">
<a href="https://github.com/sindresorhus/awesome-electron">
<img alt="Awesome" src="https://cdn.rawgit.com/sindresorhus/awesome/d7305f38d29fed78fa85652e3a63e154dd8e8829/media/badge.svg"/>
</a>
<a href="https://sourceforge.net/projects/stacer/files/" rel="nofollow">
<img alt="Download Stacer" src="https://img.shields.io/sourceforge/dt/stacer.svg"/>
</a>
<a href="http://www.kernel.org">
<img alt="Platform (GNU/Linux)" src="https://img.shields.io/badge/platform-GNU/Linux-blue.svg"/>
</a>
</p>
<p align="center">
<a href="https://sourceforge.net/projects/stacer/files/" >
<img src="https://a.fsdn.com/con/app/sf-download-button" />
</a>
</p>
## Reviews
<p align="left">
<a href="http://www.omgubuntu.co.uk/2017/01/stacer-system-optimizer-for-ubuntu">
<img width="70px" src="http://www.omgubuntu.co.uk/wp-content/themes/omgubuntu-theme-3.6.1/images/logo.png"/>
</a>
<a href="http://www.diolinux.com.br/2017/02/stacer-um-programa-para-otimizar-o-ubuntu.html">
<img width="170px" src="http://coletivo.semanadolinux.com.br/images/site/diolinux.png"/>
</a>
<a href="https://www.genbeta.com/linux/stacer-una-app-todo-en-uno-que-te-deja-monitorizar-y-optimizar-el-sistema-en-ubuntu">
<img width="160px" src="http://seanfee.com/wp-content/uploads/2014/04/Logo_genbeta.jpg"/>
</a>
<a href="http://computerhoy.com/noticias/software/stacer-herramienta-que-te-permite-optimizar-ubuntu-57974">
<img width="130px" src="http://computerhoy.com/sites/computerhoy.com/themes/computerhoy/logo-puntocom.png"/>
</a>
<a href="http://www.dobreprogramy.pl/Stacer-program-do-optymalizacji-Ubuntu-ktory-wyglada-jakby-uciekl-z-Windowsa,News,78941.html">
<img width="160px" src="http://storage.dobreprogramy.pl/artykuly/9urodziny/logoDP-napis.png"/>
</a>
<a href="http://blog.desdelinux.net/optimizar-debian-ubuntu-linux-mint-derivados-stacer/">
<img width="160px" src="http://i.imgur.com/eV1WxYZ.png"/>
</a>
<a href="http://www.techrepublic.com/article/how-to-install-stacer-for-quick-linux-system-optimization/">
<img width="160px" src="https://static1.squarespace.com/static/55afdc11e4b000b229a97849/t/55b13f1de4b044f556a02524/1437679408913/"/>
</a>
<a href="https://www.fossmint.com/stacer-ubuntu-system-optimizer/">
<img width="160px" src="https://www.fossmint.com/wp-content/uploads/2017/02/logo.png"/>
</a>
<a href="http://www.2daygeek.com/stacer-linux-system-optimizer-and-monitoring-tool/">
<img width="160px" src="http://www.2daygeek.com/wp-content/uploads/2015/12/2day-geek-new-logo-final.png"/>
</a>
<a href="http://www.noobslab.com/2017/03/stacer-sytem-optimizer-must-have.html">
<img width="160px" src="http://2.bp.blogspot.com/-Pnf0jwJPpEg/VzJxbWzYgCI/AAAAAAAAHhA/5WJys7XD_1QFHF-CfEp6Bo7VrVaubN3sgCK4B/s1600/nl-logo-1.gif"/>
</a>
</p>
### Required Packages
- curl
- systemd
## Distribution independent installation
- Install
Run `bash -c "$(wget https://gitlab.com/oguzhaninan/Stacer-Develop/raw/master/install.sh -O -)"`
- Uninstall
Run `sudo bash uninstal-stacer`
### Debian x64
1. Download `stacer_1.0.8_amd64.deb` from the [Stacer releases page](https://github.com/oguzhaninan/Stacer/releases).
2. Run `sudo dpkg -i stacer*.deb` on the downloaded package.
3. Launch Stacer using the installed `stacer` command.
### Fedora x64
1. Download `stacer_1.0.8_amd64.rpm` from the [Stacer releases page](https://github.com/oguzhaninan/Stacer/releases).
2. Run `sudo rpm --install stacer*.rpm` on the downloaded package.
3. Launch Stacer using the installed `stacer` command.
## Build from source
1. `git clone https://github.com/oguzhaninan/Stacer.git`
2. `cd Stacer`
3. `./deploy.sh`
## Screenshots
<p align="center">
<img src="https://raw.githubusercontent.com/oguzhaninan/Stacer/master/Screenshots/Screenshot-v1.0.7-1.png" width="700">
</p>
<p align="center">
<img src="https://raw.githubusercontent.com/oguzhaninan/Stacer/master/Screenshots/Screenshot-v1.0.7-2.png" width="700">
</p>
<p align="center">
<img src="https://raw.githubusercontent.com/oguzhaninan/Stacer/master/Screenshots/Screenshot-v1.0.7-3.png" width="700">
</p>
<p align="center">
<img src="https://raw.githubusercontent.com/oguzhaninan/Stacer/master/Screenshots/Screenshot-v1.0.7-4.png" width="700">
</p>
<p align="center">
<img src="https://raw.githubusercontent.com/oguzhaninan/Stacer/master/Screenshots/Screenshot-v1.0.7-5.png" width="700">
</p>
<p align="center">
<img src="https://raw.githubusercontent.com/oguzhaninan/Stacer/master/Screenshots/Screenshot-v1.0.7-6.png" width="700">
</p>
<p align="center">
<img src="https://raw.githubusercontent.com/oguzhaninan/Stacer/master/Screenshots/Screenshot-v1.0.7-7.png" width="700">
</p>
<p align="center">
<img src="https://raw.githubusercontent.com/oguzhaninan/Stacer/master/Screenshots/Screenshot-v1.0.7-8.png" width="700">
</p>
<p align="center">
<img src="https://raw.githubusercontent.com/oguzhaninan/Stacer/master/Screenshots/Screenshot-v1.0.7-9.png" width="700">
</p>
<p align="center">
<img src="https://raw.githubusercontent.com/oguzhaninan/Stacer/master/Screenshots/Screenshot-v1.0.7-10.png" width="700">
</p>

5
Stacer.pro Normal file
View File

@@ -0,0 +1,5 @@
TEMPLATE = subdirs
SUBDIRS += \
stacer-core \
stacer

53
deploy.sh Executable file
View File

@@ -0,0 +1,53 @@
#!/bin/bash
P_DIR=$(pwd)
DIST_DIR=dist
BUILD_DIR=build
#export PATH=/qt/path/gcc_64/bin:$PATH
#export QTDIR=/qt/path/gcc_64
export QT_PLUGIN_PATH=$QTDIR/plugins
export LD_LIBRARY_PATH=$QTDIR/lib
#clean
rm -rf dist
mkdir -p $DIST_DIR/$BUILD_DIR
cd $DIST_DIR/$BUILD_DIR
#build
$QTDIR/bin/qmake -spec linux-g++ "CONFIG += release" $P_DIR/Stacer.pro && make
cd $P_DIR/$DIST_DIR/$BUILD_DIR/stacer-core && make
cd $P_DIR/$DIST_DIR/$BUILD_DIR/stacer && make
mkdir $P_DIR/$DIST_DIR/$BUILD_DIR/stacer/lib
cp $P_DIR/$DIST_DIR/$BUILD_DIR/stacer-core/libstacer-core.so.1.0.0 $P_DIR/$DIST_DIR/$BUILD_DIR/stacer/lib/libstacer-core.so.1
cd $P_DIR
lrelease stacer/stacer.pro
mkdir $P_DIR/$DIST_DIR/$BUILD_DIR/stacer/translations
mv $P_DIR/translations/*.qm $P_DIR/$DIST_DIR/$BUILD_DIR/stacer/translations
rm -rf $P_DIR/$DIST_DIR/$BUILD_DIR/stacer-core
find $P_DIR/$DIST_DIR/$BUILD_DIR/stacer \( -name "moc_*" -or -name "*.o" -or -name "qrc_*" -or -name "Makefile*" -or -name "*.a" -or -name "*.h" \) -exec rm {} \;
cd $P_DIR/$DIST_DIR/$BUILD_DIR/stacer &&
cp $P_DIR/stacer/static/logo.png stacer.png &&
cp $P_DIR/stacer.desktop stacer.desktop
cd $P_DIR
if [ "$1" == "appimage" ]; then
linuxdeployqt $DIST_DIR/$BUILD_DIR/stacer/stacer -no-translations -appimage
else
linuxdeployqt $DIST_DIR/$BUILD_DIR/stacer/stacer -no-translations
fi
rm $P_DIR/$DIST_DIR/$BUILD_DIR/stacer/{AppRun,.DirIcon}

View File

Binary file not shown.

After

Width:  |  Height:  |  Size: 17 KiB

View File

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.4 KiB

View File

Binary file not shown.

After

Width:  |  Height:  |  Size: 27 KiB

View File

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.9 KiB

View File

Binary file not shown.

After

Width:  |  Height:  |  Size: 7.3 KiB

34
install.sh Executable file
View File

@@ -0,0 +1,34 @@
#!/bin/bash
APPIMAGE_FILE=
DESKTOP_FILE=
ICON=
cd /tmp
wget $APPIMAGE_FILE
wget $DESKTOP_FILE
wget $ICON
sudo mv *.AppImage /usr/bin/stacer
sudo chmod 755 /usr/bin/stacer
sudo mv stacer.desktop /usr/share/applications/
cp /usr/share/applications/stacer.desktop ~/Desktop
sudo mv stacer.png /usr/share/icons/hicolor/128x128/apps/
# uninstall file
sudo touch /usr/bin/uninstall-stacer
sudo bash -c "echo -e '#!/bin/bash
sudo rm -f /usr/bin/stacer \\
/usr/share/applications/stacer.desktop \\
/usr/share/icons/hicolor/128x128/apps/stacer.png
rm -f /usr/bin/uninstall-stacer
echo Successfully uninstalled ' > /usr/bin/uninstall-stacer"
echo "Successfully installed"

View File

Binary file not shown.

After

Width:  |  Height:  |  Size: 22 KiB

View File

Binary file not shown.

After

Width:  |  Height:  |  Size: 14 KiB

View File

Binary file not shown.

After

Width:  |  Height:  |  Size: 18 KiB

View File

Binary file not shown.

After

Width:  |  Height:  |  Size: 32 KiB

View File

Binary file not shown.

After

Width:  |  Height:  |  Size: 6.1 KiB

View File

Binary file not shown.

After

Width:  |  Height:  |  Size: 9.6 KiB

View File

Binary file not shown.

After

Width:  |  Height:  |  Size: 12 KiB

View File

Binary file not shown.

After

Width:  |  Height:  |  Size: 13 KiB

View File

Binary file not shown.

After

Width:  |  Height:  |  Size: 14 KiB

View File

Binary file not shown.

After

Width:  |  Height:  |  Size: 12 KiB

View File

Binary file not shown.

After

Width:  |  Height:  |  Size: 13 KiB

View File

Binary file not shown.

After

Width:  |  Height:  |  Size: 15 KiB

View File

Binary file not shown.

After

Width:  |  Height:  |  Size: 25 KiB

BIN
screenshots/header.png Normal file
View File

Binary file not shown.

After

Width:  |  Height:  |  Size: 36 KiB

View File

@@ -0,0 +1,96 @@
#include "cpu_info.h"
CpuInfo::CpuInfo()
{ }
quint8 CpuInfo::getCpuCoreCount()
{
static quint8 count = 0;
if (! count)
{
QStringList cpuinfo = FileUtil::readListFromFile(PROC_CPUINFO);
if (! cpuinfo.isEmpty())
count = cpuinfo.filter(QRegExp("^processor")).count();
}
return count;
}
QList<int> CpuInfo::getCpuPercents()
{
QList<double> cpuTimes;
QList<int> cpuPercents;
QStringList times = FileUtil::readListFromFile(PROC_STAT);
if (! times.isEmpty())
{
/* user nice system idle iowait irq softirq steal guest guest_nice
cpu 4705 356 584 3699 23 23 0 0 0 0
.
cpuN 4705 356 584 3699 23 23 0 0 0 0
The meanings of the columns are as follows, from left to right:
- user: normal processes executing in user mode
- nice: niced processes executing in user mode
- system: processes executing in kernel mode
- idle: twiddling thumbs
- iowait: waiting for I/O to complete
- irq: servicing interrupts
- softirq: servicing softirqs
- steal: involuntary wait
- guest: running a normal guest
- guest_nice: running a niced guest
*/
for (int i = 0; i < CpuInfo::getCpuCoreCount()+1; ++i)
{
QStringList n_times = times.at(i).split(QRegExp("\\s+"));
n_times.removeFirst();
foreach (QString t, n_times)
cpuTimes << t.toDouble();
cpuPercents << getCpuPercent(cpuTimes, i);
cpuTimes.clear();
}
}
return cpuPercents;
}
int CpuInfo::getCpuPercent(QList<double>cpuTimes, int processor)
{
const int N = getCpuCoreCount()+1;
static QVector<double> l_idles(N);
static QVector<double> l_totals(N);
double idle, total,
idle_delta, total_delta;
int utilisation = 0;
if (cpuTimes.count() > 0) {
idle = cpuTimes.at(3) + cpuTimes.at(4); // get (idle + iowait)
foreach (double t, cpuTimes) total += t; // get total time
idle_delta = idle - l_idles[processor];
total_delta = total - l_totals[processor];
if (total_delta)
utilisation = 100 * ((total_delta - idle_delta) / total_delta);
l_idles[processor] = idle;
l_totals[processor] = total;
}
if (utilisation > 100) utilisation = 100;
else if (utilisation < 0) utilisation = 0;
return utilisation;
}

View File

@@ -0,0 +1,29 @@
#ifndef CPUINFO_H
#define CPUINFO_H
#include <QObject>
#include <QDebug>
#include <QVector>
#include "Utils/file_util.h"
#define PROC_CPUINFO "/proc/cpuinfo"
#define PROC_STAT "/proc/stat"
#include "stacer-core_global.h"
class STACERCORESHARED_EXPORT CpuInfo : public QObject
{
Q_OBJECT
public:
CpuInfo();
quint8 getCpuCoreCount();
QList<int> getCpuPercents();
private:
int getCpuPercent(QList<double>cpuTimes, int processor = 0);
};
#endif // CPUINFO_H

View File

@@ -0,0 +1,31 @@
#include "disk_info.h"
#include <QDebug>
DiskInfo::DiskInfo()
{
}
QList<Disk> DiskInfo::getDisks() const
{
return disks;
}
void DiskInfo::updateDiskInfo()
{
try {
QStringList result = CommandUtil::exec("df -Pl").split("\n");
foreach(QString line, result.filter(QRegExp("^/")))
{
Disk disk;
disk.size = line.split(QRegExp("\\s+")).at(1).toLong() << 10;
disk.used = line.split(QRegExp("\\s+")).at(2).toLong() << 10;
disk.free = line.split(QRegExp("\\s+")).at(3).toLong() << 10;
disks << disk;
}
} catch (QString &ex) {
qCritical() << ex;
}
}

View File

@@ -0,0 +1,37 @@
#ifndef DISKINFO_H
#define DISKINFO_H
#include <QObject>
#include "Utils/command_util.h"
#include "Utils/file_util.h"
#define PROC_MOUNTS "/proc/mounts"
class Disk;
#include "stacer-core_global.h"
class STACERCORESHARED_EXPORT DiskInfo : public QObject
{
Q_OBJECT
public:
DiskInfo();
QList<Disk> getDisks() const;
void updateDiskInfo();
private:
QList<Disk> disks;
};
class Disk {
public:
Disk() {}
quint64 size;
quint64 free;
quint64 used;
};
#endif // DISKINFO_H

View File

@@ -0,0 +1,53 @@
#include "memory_info.h"
MemoryInfo::MemoryInfo():
memTotal(0),
memAvailable(0),
memUsed(0)
{ }
void MemoryInfo::updateMemoryInfo()
{
QStringList lines = FileUtil::readListFromFile(PROC_MEMINFO)
.filter(QRegExp("^MemTotal|^MemAvailable|^SwapTotal|^SwapFree"));
#define getValue(l) lines.at(l).split(QRegExp("\\s+")).at(1).toLong() << 10;
memTotal = getValue(0);
memAvailable = getValue(1);
swapTotal = getValue(2);
swapFree = getValue(3)
#undef getValue
memUsed = (memTotal - memAvailable);
swapUsed = (swapTotal - swapFree);
}
quint64 MemoryInfo::getSwapUsed() const
{
return swapUsed;
}
quint64 MemoryInfo::getSwapFree() const
{
return swapFree;
}
quint64 MemoryInfo::getSwapTotal() const
{
return swapTotal;
}
quint64 MemoryInfo::getMemUsed() const
{
return memUsed;
}
quint64 MemoryInfo::getMemAvailable() const
{
return memAvailable;
}
quint64 MemoryInfo::getMemTotal() const
{
return memTotal;
}

View File

@@ -0,0 +1,42 @@
#ifndef MEMORYINFO_H
#define MEMORYINFO_H
#include <QObject>
#include <QDebug>
#include "Utils/file_util.h"
#define PROC_MEMINFO "/proc/meminfo"
#include "stacer-core_global.h"
class STACERCORESHARED_EXPORT MemoryInfo : public QObject
{
Q_OBJECT
public:
MemoryInfo();
void updateMemoryInfo();
quint64 getMemTotal() const;
quint64 getMemAvailable() const;
quint64 getMemUsed() const;
quint64 getSwapTotal() const;
quint64 getSwapFree() const;
quint64 getSwapUsed() const;
private:
// memory
quint64 memTotal;
quint64 memAvailable;
quint64 memUsed;
// swap
quint64 swapTotal;
quint64 swapFree;
quint64 swapUsed;
};
#endif // MEMORYINFO_H

View File

@@ -0,0 +1,43 @@
#include "network_info.h"
NetworkInfo::NetworkInfo()
{
QStringList lines = FileUtil::readListFromFile(PROC_NET_ROUTE);
if(lines.count() > 2)
defaultNetworkInterface = lines
.at(2)
.split(QRegExp("\\s+"))
.first();
else
defaultNetworkInterface = "";
rxPath = QString("/sys/class/net/%1/statistics/rx_bytes")
.arg(defaultNetworkInterface);
txPath = QString("/sys/class/net/%1/statistics/tx_bytes")
.arg(defaultNetworkInterface);
}
QString NetworkInfo::getDefaultNetworkInterface() const
{
return defaultNetworkInterface;
}
quint64 NetworkInfo::getRXbytes()
{
quint64 rx = FileUtil::readStringFromFile(rxPath)
.trimmed()
.toLong();
return rx;
}
quint64 NetworkInfo::getTXbytes()
{
quint64 tx = FileUtil::readStringFromFile(txPath)
.trimmed()
.toLong();
return tx;
}

View File

@@ -0,0 +1,33 @@
#ifndef NETWORK_INFO_H
#define NETWORK_INFO_H
#include <QObject>
#include <QDebug>
#include "Utils/file_util.h"
#include "Utils/command_util.h"
#define PROC_NET_ROUTE "/proc/net/route"
#include "stacer-core_global.h"
class STACERCORESHARED_EXPORT NetworkInfo : public QObject
{
Q_OBJECT
public:
NetworkInfo();
QString getDefaultNetworkInterface() const;
quint64 getRXbytes();
quint64 getTXbytes();
private:
QString defaultNetworkInterface;
QString rxPath;
QString txPath;
};
#endif // NETWORK_INFO_H

View File

@@ -0,0 +1,146 @@
#include "process.h"
Process::Process()
{
}
pid_t Process::getPid() const
{
return pid;
}
void Process::setPid(const pid_t &value)
{
pid = value;
}
quint64 Process::getRss() const
{
return rss;
}
void Process::setRss(const quint64 &value)
{
rss = value;
}
double Process::getPmem() const
{
return pmem;
}
void Process::setPmem(double value)
{
pmem = value;
}
quint64 Process::getVsize() const
{
return vsize;
}
void Process::setVsize(const quint64 &value)
{
vsize = value;
}
QString Process::getUname() const
{
return uname;
}
void Process::setUname(const QString &value)
{
uname = value;
}
double Process::getPcpu() const
{
return pcpu;
}
void Process::setPcpu(double value)
{
pcpu = value;
}
QString Process::getCmd() const
{
return cmd;
}
void Process::setCmd(const QString &value)
{
cmd = value;
}
QString Process::getStartTime() const
{
return startTime;
}
void Process::setStartTime(const QString &value)
{
startTime = value;
}
QString Process::getState() const
{
return state;
}
void Process::setState(const QString &value)
{
state = value;
}
QString Process::getGroup() const
{
return group;
}
void Process::setGroup(const QString &value)
{
group = value;
}
int Process::getNice() const
{
return nice;
}
void Process::setNice(int value)
{
nice = value;
}
QString Process::getCpuTime() const
{
return cpuTime;
}
void Process::setCpuTime(const QString &value)
{
cpuTime = value;
}
QString Process::getSession() const
{
return session;
}
void Process::setSession(const QString &value)
{
session = value;
}
QString Process::getSeat() const
{
return seat;
}
void Process::setSeat(const QString &value)
{
seat = value;
}

View File

@@ -0,0 +1,80 @@
#ifndef PROCESS_H
#define PROCESS_H
#include <QObject>
#include <QDebug>
#include "Utils/file_util.h"
// defines
#define PROC_PID_CMD "/proc/%1/comm"
#define PROC_PID_STATUS "/proc/%1/comm"
#include "stacer-core_global.h"
class STACERCORESHARED_EXPORT Process {
public:
Process();
pid_t getPid() const;
void setPid(const pid_t &value);
quint64 getRss() const;
void setRss(const quint64 &value);
double getPmem() const;
void setPmem(double value);
quint64 getVsize() const;
void setVsize(const quint64 &value);
QString getUname() const;
void setUname(const QString &value);
double getPcpu() const;
void setPcpu(double value);
QString getStartTime() const;
void setStartTime(const QString &value);
QString getState() const;
void setState(const QString &value);
QString getGroup() const;
void setGroup(const QString &value);
int getNice() const;
void setNice(int value);
QString getCpuTime() const;
void setCpuTime(const QString &value);
QString getSession() const;
void setSession(const QString &value);
QString getSeat() const;
void setSeat(const QString &value);
QString getCmd() const;
void setCmd(const QString &value);
private:
pid_t pid;
quint64 rss;
double pmem;
quint64 vsize;
QString uname;
double pcpu;
QString startTime;
QString state;
QString group;
int nice;
QString cpuTime;
QString session;
QString seat;
QString cmd;
};
#endif // PROCESS_H

View File

@@ -0,0 +1,56 @@
#include "process_info.h"
ProcessInfo::ProcessInfo()
{
}
void ProcessInfo::updateProcesses()
{
processList.clear();
try {
QStringList columns = { "pid", "rss", "pmem", "vsize", "uname", "pcpu", "start_time",
"state", "group", "nice", "cputime", "session", "seat", "cmd"};
QStringList lines = CommandUtil::exec("ps", {"ax", "-eo", columns.join(","), "--no-headings"})
.trimmed()
.split("\n");
if (! lines.isEmpty()) {
foreach (QString line, lines) {
QStringList procLine = line.trimmed().split(QRegExp("\\s+"));
if (procLine.count() >= columns.count()) {
Process proc;
proc.setPid(procLine.at(0).toLong());
proc.setRss(procLine.at(1).toLong() << 10);
proc.setPmem(procLine.at(2).toDouble());
proc.setVsize(procLine.at(3).toLong() << 10);
proc.setUname(procLine.at(4));
proc.setPcpu(procLine.at(5).toDouble());
proc.setStartTime(procLine.at(6));
proc.setState(procLine.at(7));
proc.setGroup(procLine.at(8));
proc.setNice(procLine.at(9).toInt());
proc.setCpuTime(procLine.at(10));
proc.setSession(procLine.at(11));
proc.setSeat(procLine.at(12));
proc.setCmd(procLine.at(13));
processList << proc;
}
}
}
} catch (QString &ex) {
qCritical() << ex;
}
}
QList<Process> ProcessInfo::getProcessList() const
{
return processList;
}

View File

@@ -0,0 +1,30 @@
#ifndef PROCESS_INFO_H
#define PROCESS_INFO_H
#include <QObject>
#include <QDebug>
#include <Utils/file_util.h>
#include <Utils/command_util.h>
#include "process.h"
#define PROC_PID_CMD "/proc/%1/comm"
#include "stacer-core_global.h"
class STACERCORESHARED_EXPORT ProcessInfo : public QObject
{
Q_OBJECT
public:
ProcessInfo();
QList<Process> getProcessList() const;
public slots:
void updateProcesses();
private:
QList<Process> processList;
};
#endif // PROCESS_INFO_H

View File

@@ -0,0 +1,104 @@
#include "system_info.h"
SystemInfo::SystemInfo() :
info(new QSysInfo)
{
QStringList lines = FileUtil::readListFromFile(PROC_CPUINFO)
.filter(QRegExp("^model name"));
if (! lines.isEmpty()) {
QStringList model = lines.first().split(":").at(1).split("@");
if ( model.count() > 1) {
this->cpuModel = model.at(0).trimmed().replace(QRegExp("\\s+"), " ");
this->cpuSpeed = model.at(1).trimmed().replace(QRegExp("\\s+"), " ");
}
}
else {
this->cpuModel = tr("Unknown");
this->cpuSpeed = tr("Unknown");
}
CpuInfo ci;
this->cpuCore = QString::number(ci.getCpuCoreCount());
// get username
QString name = qgetenv("USER");
if (name.isEmpty())
name = qgetenv("USERNAME");
try {
if (name.isEmpty())
name = CommandUtil::exec("whoami").trimmed();
} catch (QString &ex) {
qCritical() << ex;
}
username = name;
}
QString SystemInfo::getUsername() const
{
return username;
}
QString SystemInfo::getHostname()
{
return QSysInfo::machineHostName();
}
QString SystemInfo::getPlatform()
{
return QString("%1 %2")
.arg(QSysInfo::kernelType())
.arg(QSysInfo::currentCpuArchitecture());
}
QString SystemInfo::getDistribution()
{
return QSysInfo::prettyProductName();
}
QString SystemInfo::getKernel()
{
return QSysInfo::kernelVersion();
}
QString SystemInfo::getCpuModel()
{
return this->cpuModel;
}
QString SystemInfo::getCpuSpeed()
{
return this->cpuSpeed;
}
QString SystemInfo::getCpuCore()
{
return this->cpuCore;
}
QFileInfoList SystemInfo::getCrashReports()
{
QDir reports("/var/crash");
return reports.entryInfoList(QDir::Files);
}
QFileInfoList SystemInfo::getAppLogs()
{
QDir logs("/var/log");
return logs.entryInfoList(QDir::Files | QDir::Dirs | QDir::NoDotAndDotDot);
}
QFileInfoList SystemInfo::getAppCaches()
{
QString homePath = QStandardPaths::writableLocation(QStandardPaths::HomeLocation);
QDir caches(homePath + "/.cache");
return caches.entryInfoList(QDir::Files | QDir::Dirs | QDir::NoDotAndDotDot);
}

View File

@@ -0,0 +1,47 @@
#ifndef SYSTEMINFO_H
#define SYSTEMINFO_H
#include <QObject>
#include <QSysInfo>
#include <QMap>
#include <QDebug>
#include "Utils/file_util.h"
#include "Utils/format_util.h"
#include "Utils/command_util.h"
#include "Info/cpu_info.h"
#define PROC_CPUINFO "/proc/cpuinfo"
#include "stacer-core_global.h"
class STACERCORESHARED_EXPORT SystemInfo : public QObject
{
Q_OBJECT
public:
SystemInfo();
QString getHostname();
QString getPlatform();
QString getDistribution();
QString getKernel();
QString getCpuModel();
QString getCpuSpeed();
QString getCpuCore();
QFileInfoList getCrashReports();
QFileInfoList getAppLogs();
QFileInfoList getAppCaches();
QString getUsername() const;
private:
QString cpuCore;
QString cpuModel;
QString cpuSpeed;
QSysInfo *info;
QString username;
};
#endif // SYSTEMINFO_H

View File

@@ -0,0 +1,168 @@
#include "package_tool.h"
PackageTool::PackageTool()
{
if (CommandUtil::isExecutable("apt-get")) {
currentPackageTool = APT;
} else if (CommandUtil::isExecutable("dnf")) {
currentPackageTool = DNF;
} else if (CommandUtil::isExecutable("yum")) {
currentPackageTool = YUM;
} else if (CommandUtil::isExecutable("pacman")) {
currentPackageTool = PACMAN;
} else if (CommandUtil::isExecutable("zypper")) {
currentPackageTool = ZYPPER;
} else {
currentPackageTool = UNKNOWN;
}
}
PackageTool::PackageTools PackageTool::getCurrentPackageTool() const
{
return currentPackageTool;
}
/***********
* DPKG /var/cache/yum/development/packages/
***********/
QFileInfoList PackageTool::getDpkgPackageCaches()
{
QDir caches("/var/cache/apt/archives/");
return caches.entryInfoList(QDir::Files);
}
QStringList PackageTool::getDpkgPackages()
{
QStringList packageList = {};
try {
packageList = CommandUtil::exec("bash", {"-c", "dpkg --get-selections 2> /dev/null"})
.trimmed()
.split("\n");
for (int i = 0; i < packageList.count(); ++i)
packageList[i] = packageList.at(i).split(QRegExp("\\s+")).first();
} catch(QString &ex) {
qCritical() << ex;
}
return packageList;
}
bool PackageTool::dpkgRemovePackages(QStringList packages)
{
try {
packages.insert(0, "remove");
packages.insert(1, "-y");
CommandUtil::sudoExec("apt-get", packages);
return true;
} catch(QString &ex) {
qCritical() << ex;
}
return false;
}
/**********
* RPM
**********/
QStringList PackageTool::getRpmPackages()
{
QStringList packageList = {};
try {
packageList = CommandUtil::exec("bash", {"-c", "rpm -qa 2> /dev/null"})
.trimmed()
.split("\n");
} catch(QString &ex) {
qCritical() << ex;
}
return packageList;
}
bool PackageTool::dnfRemovePackages(QStringList packages)
{
try {
packages.insert(0, "remove");
packages.insert(1, "-y");
CommandUtil::sudoExec("dnf", packages);
return true;
} catch(QString &ex) {
qCritical() << ex;
}
return false;
}
bool PackageTool::yumRemovePackages(QStringList packages)
{
try {
packages.insert(0, "remove");
packages.insert(1, "-y");
CommandUtil::sudoExec("yum", packages);
return true;
} catch(QString &ex) {
qCritical() << ex;
}
return false;
}
/**********
* PACMAN
**********/
QFileInfoList PackageTool::getPacmanPackageCaches()
{
QDir caches("/var/cache/pacman/pkg/");
return caches.entryInfoList(QDir::Files);
}
QStringList PackageTool::getPacmanPackages()
{
QStringList packageList = {};
try {
packageList = CommandUtil::exec("bash", {"-c", "pacman -Q 2> /dev/null"})
.trimmed()
.split("\n");
for (int i = 0; i < packageList.count(); ++i)
packageList[i] = packageList.at(i).split(QRegExp("\\s+")).first();
} catch(QString &ex) {
qCritical() << ex;
}
return packageList;
}
bool PackageTool::pacmanRemovePackages(QStringList packages)
{
try {
packages.push_back("--noconfirm");
packages.push_back("-R");
CommandUtil::sudoExec("pacman", packages);
return true;
} catch(QString &ex) {
qCritical() << ex;
}
return false;
}

View File

@@ -0,0 +1,51 @@
#ifndef PACKAGE_TOOL_H
#define PACKAGE_TOOL_H
#include <QObject>
#include <QDebug>
#include <thread>
#include "Utils/command_util.h"
#include "Utils/file_util.h"
#include "stacer-core_global.h"
class STACERCORESHARED_EXPORT PackageTool : public QObject
{
Q_OBJECT
public:
enum PackageTools {
APT, // debian
DNF, // fedora
YUM, // fedora
PACMAN, // arch
ZYPPER, // opensuse
UNKNOWN
};
public:
PackageTool();
public slots:
// APT
QFileInfoList getDpkgPackageCaches();
QStringList getDpkgPackages();
bool dpkgRemovePackages(QStringList packages);
// DNF - YUM
QStringList getRpmPackages();
bool dnfRemovePackages(QStringList packages);
bool yumRemovePackages(QStringList packages);
// Arch
QFileInfoList getPacmanPackageCaches();
QStringList getPacmanPackages();
bool pacmanRemovePackages(QStringList packages);
PackageTools getCurrentPackageTool() const;
private:
PackageTools currentPackageTool;
};
#endif // PACKAGE_TOOL_H

View File

@@ -0,0 +1,104 @@
#include "service_tool.h"
ServiceTool::ServiceTool()
{
}
QList<Service> ServiceTool::getServicesWithSystemctl()
{
QList<Service> services = {};
try {
QStringList args = { "list-unit-files", "-t", "service", "-a", "--state=enabled,disabled" };
QStringList lines = CommandUtil::exec("systemctl", args)
.split("\n")
.filter(QRegExp("[^@].service"));
foreach(QString line, lines)
{
// e.g apache2.service [enabled|disabled]
QStringList s = line.trimmed().split(QRegExp("\\s+"));
QString name = s.first().trimmed().replace(".service", "");
bool status = ! s.last().trimmed().compare("enabled");
bool active = serviceIsActive(s.first().trimmed());
Service service(name, status, active);
services << service;
}
} catch(QString &ex) {
qCritical() << ex;
}
return services;
}
bool ServiceTool::serviceIsActive(QString serviceName)
{
QStringList args = { "is-active", serviceName };
QString result("");
try {
result = CommandUtil::exec("systemctl", args);
} catch(QString &ex) {
qCritical() << ex;
}
return ! result.trimmed().compare("active");
}
bool ServiceTool::serviceIsEnabled(QString serviceName)
{
QStringList args = { "is-enabled", serviceName };
QString result("");
try {
result = CommandUtil::exec("systemctl", args);
} catch(QString &ex) {
qCritical() << ex;
}
return ! result.trimmed().compare("enabled");
}
bool ServiceTool::changeServiceStatus(QString sname, bool status)
{
try {
QStringList args = { (status ? "enable" : "disable") , sname };
CommandUtil::sudoExec("systemctl", args);
return true;
} catch(QString &ex) {
qCritical() << ex;
}
return false;
}
bool ServiceTool::changeServiceActive(QString sname, bool status)
{
try {
QStringList args = { (status ? "start" : "stop") , sname };
CommandUtil::sudoExec("systemctl", args);
return true;
} catch(QString &ex) {
qCritical() << ex;
}
return false;
}

View File

@@ -0,0 +1,40 @@
#ifndef SERVICE_TOOL_H
#define SERVICE_TOOL_H
#include <QObject>
#include <QDebug>
#include <Utils/command_util.h>
#include "stacer-core_global.h"
class STACERCORESHARED_EXPORT Service {
public:
Service(QString name, bool status, bool active) {
this->name = name;
this->status = status;
this->active = active;
}
QString name;
bool status;
bool active;
};
class ServiceTool : public QObject
{
Q_OBJECT
public:
ServiceTool();
QList<Service> getServicesWithSystemctl();
bool serviceIsActive(QString serviceName);
bool changeServiceStatus(QString sname, bool status);
bool changeServiceActive(QString sname, bool status);
bool serviceIsEnabled(QString serviceName);
private:
};
#endif // SERVICE_TOOL_H

View File

@@ -0,0 +1,57 @@
#include "command_util.h"
CommandUtil::CommandUtil()
{
}
QString CommandUtil::sudoExec(QString cmd, QStringList args)
{
args.push_front(cmd);
QString result("");
try {
result = CommandUtil::exec("pkexec", args);
} catch (QString &ex) {
qCritical() << ex;
}
return result;
}
QString CommandUtil::exec(QString cmd, QStringList args)
{
QProcess* process = new QProcess;
if(args.isEmpty())
process->start(cmd);
else
process->start(cmd, args);
process->waitForFinished();
QTextStream stdOut(process->readAllStandardOutput());
QString err = process->errorString();
process->kill();
process->close();
if (process->error() != QProcess::UnknownError)
throw err;
return stdOut.readAll().trimmed();
}
bool CommandUtil::isExecutable(QString cmd)
{
QStringList paths;
paths << "/usr/bin/" << "/bin/" << "/sbin/" << "/usr/sbin/";
foreach (QString path, paths)
if(QFile::exists(path + cmd))
return true;
return false;
}

View File

@@ -0,0 +1,24 @@
#ifndef COMMAND_UTIL_H
#define COMMAND_UTIL_H
#include <QObject>
#include <QProcess>
#include <QFile>
#include <QTextStream>
#include <QDebug>
#include "stacer-core_global.h"
class STACERCORESHARED_EXPORT CommandUtil : public QObject
{
Q_OBJECT
public:
static QString sudoExec(QString cmd, QStringList args = {});
static QString exec(QString cmd, QStringList args = {});
static bool isExecutable(QString cmd);
private:
CommandUtil();
};
#endif // COMMAND_UTIL_H

View File

@@ -0,0 +1,84 @@
#include "file_util.h"
FileUtil::FileUtil()
{
}
QString FileUtil::readStringFromFile(QString path, QIODevice::OpenMode mode)
{
QSharedPointer<QFile> file(new QFile(path));
QString data;
if(file->open(mode)) {
data = file->readAll();
file->close();
}
return data;
}
QStringList FileUtil::readListFromFile(QString path, QIODevice::OpenMode mode)
{
QStringList list = FileUtil::readStringFromFile(path, mode).trimmed().split("\n");
return list;
}
bool FileUtil::writeFile(QString path, QString content, QIODevice::OpenMode mode)
{
QFile file(path);
if(file.open(mode))
{
QTextStream stream(&file);
stream << content.toUtf8();
file.close();
return true;
}
return false;
}
QStringList FileUtil::directoryList(QString path)
{
QDir dir(path);
QStringList list;
foreach (QFileInfo info, dir.entryInfoList(QDir::NoDotAndDotDot | QDir::Files))
list << info.fileName();
return list;
}
quint64 FileUtil::getFileSize(QString path)
{
quint64 totalSize = 0;
QFileInfo info(path);
if (info.exists())
{
if (info.isFile()) {
totalSize += info.size();
}
else if (info.isDir()) {
QDir dir(path);
foreach (QFileInfo i, dir.entryInfoList(QDir::NoDotAndDotDot | QDir::Files | QDir::Dirs)) {
totalSize += getFileSize(i.absoluteFilePath());
}
}
}
return totalSize;
}

View File

@@ -0,0 +1,32 @@
#ifndef FILEUTIL_H
#define FILEUTIL_H
#include <QDebug>
#include <QFile>
#include <QDir>
#include <QTextStream>
#include <QDirIterator>
#include <QStandardPaths>
#include <QStandardPaths>
#include <QSharedPointer>
#include "stacer-core_global.h"
class STACERCORESHARED_EXPORT FileUtil : public QObject
{
Q_OBJECT
public:
static QString readStringFromFile(QString path, QIODevice::OpenMode mode = QIODevice::ReadOnly);
static QStringList readListFromFile(QString path, QIODevice::OpenMode mode = QIODevice::ReadOnly);
static bool writeFile(QString path, QString content, QIODevice::OpenMode mode = QIODevice::ReadWrite);
static QStringList directoryList(QString path);
static quint64 getFileSize(QString path);
private:
FileUtil();
};
#endif // FILEUTIL_H

View File

@@ -0,0 +1,31 @@
#include "format_util.h"
FormatUtil::FormatUtil()
{
}
QString FormatUtil::formatBytes(quint64 bytes)
{
#define formatUnit(v, u, t) QString().sprintf("%.1f %s", \
((double) v / (double) u), t)
if (bytes == 1L) // bytes
return QString("%1 byte").arg(bytes);
else if (bytes < KIBI) // bytes
return QString("%1 bytes").arg(bytes);
else if (bytes < MEBI) // KiB
return formatUnit(bytes, KIBI, "KiB");
else if (bytes < GIBI) // MiB
return formatUnit(bytes, MEBI, "MiB");
else if (bytes < TEBI) // GiB
return formatUnit(bytes, GIBI, "GiB");
else if (bytes < PEBI) // TiB
return formatUnit(bytes, TEBI, "TiB");
else if (bytes < EXBI) // PiB
return formatUnit(bytes, PEBI, "PiB");
else // EiB
return formatUnit(bytes, EXBI, "EiB");
#undef formatUnit
}

View File

@@ -0,0 +1,28 @@
#ifndef FORMAT_UTIL_H
#define FORMAT_UTIL_H
#include <QObject>
#include <QDebug>
#include "stacer-core_global.h"
class STACERCORESHARED_EXPORT FormatUtil : public QObject
{
Q_OBJECT
public:
static QString formatBytes(quint64 bytes);
private:
FormatUtil();
static const quint64 KIBI = 1L << 10;
static const quint64 MEBI = 1L << 20;
static const quint64 GIBI = 1L << 30;
static const quint64 TEBI = 1L << 40;
static const quint64 PEBI = 1L << 50;
static const quint64 EXBI = 1L << 60;
};
#endif // FORMAT_UTIL_H

View File

@@ -0,0 +1,57 @@
#-------------------------------------------------
#
# Project created by QtCreator 2017-07-02T15:48:51
#
#-------------------------------------------------
QT -= gui
TARGET = stacer-core
TEMPLATE = lib
DEFINES += STACERCORE_LIBRARY
# The following define makes your compiler emit warnings if you use
# any feature of Qt which as been marked as deprecated (the exact warnings
# depend on your compiler). Please consult the documentation of the
# deprecated API in order to know how to port your code away from it.
DEFINES += QT_DEPRECATED_WARNINGS
# You can also make your code fail to compile if you use deprecated APIs.
# In order to do so, uncomment the following line.
# You can also select to disable deprecated APIs only up to a certain version of Qt.
#DEFINES += QT_DISABLE_DEPRECATED_BEFORE=0x060000 # disables all the APIs deprecated before Qt 6.0.0
SOURCES += \
Utils/command_util.cpp \
Utils/file_util.cpp \
Info/network_info.cpp \
Info/cpu_info.cpp \
Info/disk_info.cpp \
Info/memory_info.cpp \
Info/system_info.cpp \
Utils/format_util.cpp \
Tools/service_tool.cpp \
Tools/package_tool.cpp \
Info/process_info.cpp \
Info/process.cpp
HEADERS += \
stacer-core_global.h \
Utils/command_util.h \
Info/network_info.h \
Info/cpu_info.h \
Info/disk_info.h \
Info/memory_info.h \
Info/system_info.h \
Utils/format_util.h \
Utils/file_util.h \
Tools/service_tool.h \
Tools/package_tool.h \
Info/process_info.h \
Info/process.h
unix {
target.path = /usr/lib
INSTALLS += target
}

View File

@@ -0,0 +1,12 @@
#ifndef STACERCORE_GLOBAL_H
#define STACERCORE_GLOBAL_H
#include <QtCore/qglobal.h>
#if defined(STACERCORE_LIBRARY)
# define STACERCORESHARED_EXPORT Q_DECL_EXPORT
#else
# define STACERCORESHARED_EXPORT Q_DECL_IMPORT
#endif
#endif // STACERCORE_GLOBAL_H

8
stacer.desktop Normal file
View File

@@ -0,0 +1,8 @@
[Desktop Entry]
Type=Application
Name=Stacer
Exec=stacer
Icon=stacer
Comment=System Optimizer
Categories=System
Terminal=false

View File

@@ -0,0 +1,126 @@
#include "app_manager.h"
AppManager *AppManager::_instance = NULL;
AppManager *AppManager::ins()
{
if (_instance == NULL) {
_instance = new AppManager;
}
return _instance;
}
AppManager::AppManager(QObject *parent) : QObject(parent)
{
// font settings
QFontDatabase::addApplicationFont(":/static/font/Ubuntu-R.ttf");
configPath = QStandardPaths::writableLocation(QStandardPaths::AppConfigLocation);
settings = new QSettings(QString("%1/settings.conf").arg(configPath), QSettings::NativeFormat);
loadLanguageList();
loadThemeList();
themeName = settings->value(THEME_PROP, "default").toString();
if (translator.load(QString("stacer_%1").arg(getLanguageCode()), qApp->applicationDirPath() + "/translations")) {
qApp->installTranslator(&translator);
} else {
qCritical() << "Translator could not load.";
}
styleValues = new QSettings(QString(":/static/themes/%1/style/values.ini").arg(themeName), QSettings::NativeFormat);
}
QSettings *AppManager::getStyleValues() const
{
return styleValues;
}
/************
* LANGUAGE
***********/
void AppManager::loadLanguageList()
{
QJsonArray langs = QJsonDocument::fromJson(FileUtil::readStringFromFile(":/static/languages.json").toUtf8())
.array();
for (int i = 0; i < langs.count(); ++i) {
QJsonObject ob = langs.at(i).toObject();
languageList.insert(ob["value"].toString(), ob["text"].toString());
}
}
void AppManager::setLanguage(QString value)
{
settings->setValue(LANG_PROP, value);
}
QString AppManager::getLanguageCode()
{
return settings->value(LANG_PROP, "en").toString();
}
QMap<QString, QString> AppManager::getLanguageList()
{
return languageList;
}
/************
* THEME
***********/
void AppManager::loadThemeList()
{
QJsonArray themes = QJsonDocument::fromJson(FileUtil::readStringFromFile(":/static/themes.json").toUtf8())
.array();
for (int i = 0; i < themes.count(); ++i) {
QJsonObject ob = themes.at(i).toObject();
themeList.insert(ob["value"].toString(), ob["text"].toString());
}
}
QMap<QString, QString> AppManager::getThemeList() const
{
return themeList;
}
QString AppManager::getThemeName() const
{
return themeName;
}
void AppManager::updateStylesheet()
{
styleValues = new QSettings(QString(":/static/themes/%1/style/values.ini").arg(themeName), QSettings::NativeFormat);
stylesheetFileContent = FileUtil::readStringFromFile(QString(":/static/themes/%1/style/style.qss").arg(themeName));
// set values
foreach (QString key, styleValues->allKeys()) {
stylesheetFileContent.replace(key, styleValues->value(key).toString());
}
qApp->setStyleSheet(stylesheetFileContent);
emit changedTheme();
}
void AppManager::setThemeName(const QString &value)
{
themeName = value;
settings->setValue(THEME_PROP, value);
}
QString AppManager::getStylesheetFileContent() const
{
return stylesheetFileContent;
}

View File

@@ -0,0 +1,59 @@
#ifndef APP_MANAGER_H
#define APP_MANAGER_H
#include <QApplication>
#include <QObject>
#include <QMap>
#include <QStandardPaths>
#include <QSettings>
#include <QJsonDocument>
#include <QJsonArray>
#include <QJsonObject>
#include <QTranslator>
#include <QFontDatabase>
#include <Utils/file_util.h>
#include <QDebug>
#define THEME_PROP "ThemeName"
#define LANG_PROP "Language"
class AppManager : public QObject
{
Q_OBJECT
public:
static AppManager *ins();
QString getLanguageCode();
void setLanguage(QString value);
QMap<QString, QString> getLanguageList();
void loadLanguageList();
QString getStylesheetFileContent() const;
void updateStylesheet();
void setThemeName(const QString &value);
QString getThemeName() const;
QMap<QString, QString> getThemeList() const;
void loadThemeList();
QSettings *getStyleValues() const;
signals:
void changedTheme();
private:
static AppManager *_instance;
explicit AppManager(QObject *parent = nullptr);
private:
QTranslator translator;
QString configPath;
QString themeName;
QSettings *settings;
QSettings *styleValues;
QMap<QString, QString> languageList;
QMap<QString, QString> themeList;
QString stylesheetFileContent;
};
#endif // APP_MANAGER_H

View File

@@ -0,0 +1,121 @@
#include "info_manager.h"
InfoManager::InfoManager()
{
}
InfoManager *InfoManager::_instance = NULL;
InfoManager *InfoManager::ins()
{
if(_instance == NULL)
_instance = new InfoManager;
return _instance;
}
QString InfoManager::getUserName()
{
return si.getUsername();
}
/********************
* CPU INFORMATION
*******************/
quint8 InfoManager::getCpuCoreCount()
{
return ci.getCpuCoreCount();
}
QList<int> InfoManager::getCpuPercents()
{
return ci.getCpuPercents();
}
/********************
* MEMORY INFORMATION
*******************/
void InfoManager::updateMemoryInfo()
{
mi.updateMemoryInfo();
}
quint64 InfoManager::getSwapUsed()
{
return mi.getSwapUsed();
}
quint64 InfoManager::getSwapTotal()
{
return mi.getSwapTotal();
}
quint64 InfoManager::getMemUsed()
{
return mi.getMemUsed();
}
quint64 InfoManager::getMemTotal()
{
return mi.getMemTotal();
}
/********************
* DISK INFORMATION
*******************/
QList<Disk> InfoManager::getDisks()
{
return di.getDisks();
}
void InfoManager::updateDiskInfo()
{
return di.updateDiskInfo();
}
/********************
* NETWORK INFORMATION
*******************/
quint64 InfoManager::getRXbytes()
{
return ni.getRXbytes();
}
quint64 InfoManager::getTXbytes()
{
return ni.getTXbytes();
}
/********************
* CLEANER INFORMATION
*******************/
QFileInfoList InfoManager::getCrashReports()
{
return si.getCrashReports();
}
QFileInfoList InfoManager::getAppLogs()
{
return si.getAppLogs();
}
QFileInfoList InfoManager::getAppCaches()
{
return si.getAppCaches();
}
/********************
* PROCESSES INFORMATION
*******************/
void InfoManager::updateProcesses()
{
pi.updateProcesses();
}
QList<Process> InfoManager::getProcesses()
{
return pi.getProcessList();
}

View File

@@ -0,0 +1,54 @@
#ifndef INFO_MANAGER_H
#define INFO_MANAGER_H
#include <QObject>
#include <Info/cpu_info.h>
#include <Info/disk_info.h>
#include <Info/memory_info.h>
#include <Info/network_info.h>
#include <Info/system_info.h>
#include <Info/process_info.h>
#include <Utils/format_util.h>
class InfoManager
{
public:
static InfoManager *ins();
quint8 getCpuCoreCount();
QList<int> getCpuPercents();
quint64 getSwapUsed();
quint64 getSwapTotal();
quint64 getMemUsed();
quint64 getMemTotal();
void updateMemoryInfo();
quint64 getRXbytes();
quint64 getTXbytes();
QList<Disk> getDisks();
void updateDiskInfo();
QFileInfoList getCrashReports();
QFileInfoList getAppLogs();
QFileInfoList getAppCaches();
void updateProcesses();
QList<Process> getProcesses();
QString getUserName();
private:
InfoManager();
static InfoManager *_instance;
private:
CpuInfo ci;
DiskInfo di;
MemoryInfo mi;
NetworkInfo ni;
SystemInfo si;
ProcessInfo pi;
};
#endif // INFO_MANAGER_H

View File

@@ -0,0 +1,110 @@
#include "tool_manager.h"
ToolManager *ToolManager::_instance = NULL;
ToolManager *ToolManager::ins()
{
if(_instance == NULL)
_instance = new ToolManager;
return _instance;
}
ToolManager::ToolManager() :
st(new ServiceTool),
pt(new PackageTool)
{
}
/******************
* SERVICES
*****************/
QList<Service> ToolManager::getServices()
{
return st->getServicesWithSystemctl();
}
bool ToolManager::changeServiceStatus(QString sname, bool status)
{
return st->changeServiceStatus(sname, status);
}
bool ToolManager::changeServiceActive(QString sname, bool status)
{
return st->changeServiceActive(sname, status);
}
bool ToolManager::serviceIsActive(QString sname)
{
return st->serviceIsActive(sname);
}
bool ToolManager::serviceIsEnabled(QString sname)
{
return st->serviceIsEnabled(sname);
}
/******************
* PACKAGES
*****************/
QStringList ToolManager::getPackages()
{
switch (pt->getCurrentPackageTool()) {
case PackageTool::PackageTools::APT:
return pt->getDpkgPackages();
break;
case PackageTool::PackageTools::YUM:
case PackageTool::PackageTools::DNF:
return pt->getRpmPackages();
break;
case PackageTool::PackageTools::PACMAN:
return pt->getPacmanPackages();
break;
default:
return QStringList();
break;
}
}
QFileInfoList ToolManager::getPackageCaches()
{
switch (pt->getCurrentPackageTool()) {
case PackageTool::PackageTools::APT:
return pt->getDpkgPackageCaches();
break;
case PackageTool::PackageTools::YUM:
case PackageTool::PackageTools::DNF:
return pt->getPacmanPackageCaches();
break;
case PackageTool::PackageTools::PACMAN:
return pt->getPacmanPackageCaches();
break;
default:
return QFileInfoList();
break;
}
}
void ToolManager::uninstallPackages(QStringList packages)
{
uninstallStarted();
switch (pt->getCurrentPackageTool()) {
case PackageTool::PackageTools::APT:
pt->dpkgRemovePackages(packages);
break;
case PackageTool::PackageTools::YUM:
pt->yumRemovePackages(packages);
break;
case PackageTool::PackageTools::DNF:
pt->dnfRemovePackages(packages);
break;
case PackageTool::PackageTools::PACMAN:
pt->pacmanRemovePackages(packages);
break;
}
uninstallFinished();
}

View File

@@ -0,0 +1,41 @@
#ifndef TOOL_MANAGER_H
#define TOOL_MANAGER_H
#include <QObject>
#include <QDebug>
#include <Tools/service_tool.h>
#include <Tools/package_tool.h>
class ToolManager : public QObject
{
Q_OBJECT
public:
static ToolManager *ins();
public:
QList<Service> getServices();
QStringList getPackages();
QFileInfoList getPackageCaches();
public slots:
bool changeServiceStatus(QString sname, bool status);
bool changeServiceActive(QString sname, bool status);
bool serviceIsActive(QString sname);
bool serviceIsEnabled(QString sname);
void uninstallPackages(QStringList packages);
signals:
void uninstallFinished();
void uninstallStarted();
private:
ToolManager();
static ToolManager *_instance;
ServiceTool *st;
PackageTool *pt;
};
#endif // TOOL_MANAGER_H

View File

@@ -0,0 +1,70 @@
#include "circlebar.h"
#include "ui_circlebar.h"
CircleBar::~CircleBar()
{
delete ui;
delete chart;
delete chartView;
delete series;
}
CircleBar::CircleBar(QString title, QStringList colors, QWidget *parent) :
QWidget(parent),
ui(new Ui::CircleBar),
colors(colors),
chart(new QChart),
chartView(new QChartView(chart)),
series(new QPieSeries)
{
ui->setupUi(this);
ui->chartTitle->setText(title);
init();
}
void CircleBar::init()
{
// series settings
series->setHoleSize(0.67);
series->setPieSize(165);
series->setPieStartAngle(-115);
series->setPieEndAngle(115);
series->setLabelsVisible(false);
series->append("1", 0);
series->append("2", 0);
series->slices().first()->setBorderColor("transparent");
series->slices().last()->setBorderColor("transparent");
QConicalGradient gradient;
gradient.setAngle(115);
for (int i = 0; i < colors.count(); ++i)
gradient.setColorAt(i, QColor(colors.at(i)));
series->slices().first()->setBrush(gradient);
// chart settings
chart->setBackgroundBrush(QBrush("transparent"));
chart->setContentsMargins(-15, -18, -15, -60);
chart->addSeries(series);
chart->legend()->hide();
// chartview settings
chartView->setRenderHint(QPainter::Antialiasing);
ui->chartLayout->insertWidget(1, chartView);
connect(AppManager::ins(), &AppManager::changedTheme, this, [this](){
chartView->setBackgroundBrush(QColor(AppManager::ins()->getStyleValues()->value("@circleChartBackgroundColor").toString()));
series->slices().last()->setColor(AppManager::ins()->getStyleValues()->value("@pageContent").toString()); // trail color
});
}
void CircleBar::setValue(int value, QString valueText)
{
series->slices().first()->setValue(value);
series->slices().last()->setValue(100 - value);
ui->chartValue->setText(valueText);
}

View File

@@ -0,0 +1,37 @@
#ifndef CIRCLEBAR_H
#define CIRCLEBAR_H
#include <QWidget>
#include <QtCharts>
#include "Managers/app_manager.h"
namespace Ui {
class CircleBar;
}
class CircleBar : public QWidget
{
Q_OBJECT
public:
explicit CircleBar(QString title, QStringList colors, QWidget *parent = 0);
~CircleBar();
public slots:
void setValue(int value, QString valueText);
private slots:
void init();
private:
Ui::CircleBar *ui;
private:
QStringList colors;
QChart *chart;
QChartView *chartView;
QPieSeries *series;
};
#endif // CIRCLEBAR_H

View File

@@ -0,0 +1,89 @@
<?xml version="1.0" encoding="UTF-8"?>
<ui version="4.0">
<class>CircleBar</class>
<widget class="QWidget" name="CircleBar">
<property name="geometry">
<rect>
<x>0</x>
<y>0</y>
<width>383</width>
<height>317</height>
</rect>
</property>
<property name="sizePolicy">
<sizepolicy hsizetype="Expanding" vsizetype="Expanding">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="windowTitle">
<string notr="true"/>
</property>
<layout class="QVBoxLayout" name="verticalLayout">
<property name="spacing">
<number>0</number>
</property>
<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="QWidget" name="chartWidget" native="true">
<property name="sizePolicy">
<sizepolicy hsizetype="Expanding" vsizetype="Expanding">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="styleSheet">
<string notr="true"/>
</property>
<layout class="QVBoxLayout" name="chartLayout">
<property name="spacing">
<number>0</number>
</property>
<property name="leftMargin">
<number>0</number>
</property>
<property name="topMargin">
<number>10</number>
</property>
<property name="rightMargin">
<number>0</number>
</property>
<property name="bottomMargin">
<number>10</number>
</property>
<item alignment="Qt::AlignHCenter|Qt::AlignTop">
<widget class="QLabel" name="chartTitle">
<property name="styleSheet">
<string notr="true"/>
</property>
<property name="text">
<string notr="true">Title</string>
</property>
</widget>
</item>
<item alignment="Qt::AlignHCenter|Qt::AlignBottom">
<widget class="QLabel" name="chartValue">
<property name="text">
<string notr="true">Value</string>
</property>
</widget>
</item>
</layout>
</widget>
</item>
</layout>
</widget>
<resources/>
<connections/>
</ui>

View File

@@ -0,0 +1,198 @@
#include "dashboard_page.h"
#include "ui_dashboard_page.h"
DashboardPage::~DashboardPage()
{
delete ui;
delete cpuBar;
delete memBar;
delete diskBar;
delete downloadBar;
delete uploadBar;
delete timer;
}
DashboardPage::DashboardPage(QWidget *parent) :
QWidget(parent),
ui(new Ui::DashboardPage),
cpuBar(new CircleBar(tr("CPU"), {"#A8E063", "#56AB2F"})),
memBar(new CircleBar(tr("MEMORY"), {"#FFB75E", "#ED8F03"})),
diskBar(new CircleBar(tr("DISK"), {"#DC2430", "#7B4397"})),
downloadBar(new LineBar(tr("DOWNLOAD"))),
uploadBar(new LineBar(tr("UPLOAD"))),
timer(new QTimer),
im(InfoManager::ins())
{
ui->setupUi(this);
init();
systemInformationInit();
}
void DashboardPage::init()
{
// Circle bars
ui->circleBarsLayout->addWidget(cpuBar);
ui->circleBarsLayout->addWidget(memBar);
ui->circleBarsLayout->addWidget(diskBar);
// line bars
ui->lineBarsLayout->addWidget(downloadBar);
ui->lineBarsLayout->addWidget(uploadBar);
// connections
connect(timer, &QTimer::timeout, this, &DashboardPage::updateCpuBar);
connect(timer, &QTimer::timeout, this, &DashboardPage::updateMemoryBar);
connect(timer, &QTimer::timeout, this, &DashboardPage::updateNetworkBar);
QTimer *timerDisk = new QTimer;
connect(timerDisk, &QTimer::timeout, this, &DashboardPage::updateDiskBar);
timerDisk->start(10 * 1000);
timer->start(1 * 1000);
// initialization
updateCpuBar();
updateMemoryBar();
updateDiskBar();
updateNetworkBar();
ui->updateBarWidget->hide();
// check update
checkUpdate();
}
void DashboardPage::checkUpdate()
{
QString requestResult;
if (CommandUtil::isExecutable("curl")) {
try {
requestResult = CommandUtil::exec("curl", { "https://api.github.com/repos/oguzhaninan/Stacer/releases/latest" });
} catch (QString &ex) {
qCritical() << ex;
}
if (! requestResult.isEmpty()) {
QJsonDocument result = QJsonDocument::fromJson(requestResult.toUtf8());
QRegExp ex("[0-9].[0-9].[0-9]");
ex.indexIn(result.object().value("tag_name").toString());
QString version;
if (! ex.captureCount())
version = ex.cap();
if (qApp->applicationVersion() != version) {
ui->updateBarWidget->show();
}
}
}
}
void DashboardPage::on_downloadUpdateBtn_clicked()
{
QDesktopServices::openUrl(QUrl("https://github.com/oguzhaninan/Stacer/releases/latest"));
}
void DashboardPage::systemInformationInit()
{
// get system information
SystemInfo sysInfo;
QStringList infos;
infos
<< tr("Hostname: %1").arg(sysInfo.getHostname())
<< tr("Platform: %1").arg(sysInfo.getPlatform())
<< tr("Distribution: %1").arg(sysInfo.getDistribution())
<< tr("Kernel Release: %1").arg(sysInfo.getKernel())
<< tr("CPU Model: %1").arg(sysInfo.getCpuModel())
<< tr("CPU Speed: %1").arg(sysInfo.getCpuSpeed())
<< tr("CPU Core: %1").arg(sysInfo.getCpuCore());
QStringListModel *systemInfoModel = new QStringListModel(infos);
ui->systemInfoList->setModel(systemInfoModel);
}
void DashboardPage::updateCpuBar()
{
int cpuUsedPercent = im->getCpuPercents().at(0);
cpuBar->setValue(cpuUsedPercent, QString("%1%").arg(cpuUsedPercent));
}
void DashboardPage::updateMemoryBar()
{
im->updateMemoryInfo();
int memUsedPercent = 0;
if (im->getMemTotal())
memUsedPercent = ((double)im->getMemUsed() / (double)im->getMemTotal()) * 100.0;
QString f_memUsed = FormatUtil::formatBytes(im->getMemUsed());
QString f_memTotal = FormatUtil::formatBytes(im->getMemTotal());
memBar->setValue(memUsedPercent, QString("%1 / %2")
.arg(f_memUsed)
.arg(f_memTotal));
}
void DashboardPage::updateDiskBar()
{
im->updateDiskInfo();
if(! im->getDisks().isEmpty())
{
quint64 size = im->getDisks().at(0).size;
quint64 used = im->getDisks().at(0).used;
QString sizeText = FormatUtil::formatBytes(size);
QString usedText = FormatUtil::formatBytes(used);
int diskPercent = 0;
if (size)
diskPercent = ( (double) used / (double) size ) * 100.0;
diskBar->setValue(diskPercent, QString("%1 / %2")
.arg(usedText)
.arg(sizeText));
}
}
void DashboardPage::updateNetworkBar()
{
static quint64 l_RXbytes = im->getRXbytes();
static quint64 l_TXbytes = im->getTXbytes();
static quint64 max_RXbytes = 1L << 20; // 1 MEBI
static quint64 max_TXbytes = 1L << 20; // 1 MEBI
quint64 RXbytes = im->getRXbytes();
quint64 TXbytes = im->getTXbytes();
quint64 d_RXbytes = (RXbytes - l_RXbytes);
quint64 d_TXbytes = (TXbytes - l_TXbytes);
QString downText = FormatUtil::formatBytes(d_RXbytes);
QString upText = FormatUtil::formatBytes(d_TXbytes);
int downPercent = ((double) d_RXbytes / (double) max_RXbytes) * 100.0;
int upPercent = ((double) d_TXbytes / (double) max_TXbytes) * 100.0;
downloadBar->setValue(downPercent,
QString("%1/s").arg(downText),
tr("Total: %1").arg(FormatUtil::formatBytes(RXbytes)));
uploadBar->setValue(upPercent,
QString("%1/s").arg(upText),
tr("Total: %1").arg(FormatUtil::formatBytes(TXbytes)));
max_RXbytes = qMax(max_RXbytes, d_RXbytes);
max_TXbytes = qMax(max_TXbytes, d_TXbytes);
l_RXbytes = RXbytes;
l_TXbytes = TXbytes;
}

View File

@@ -0,0 +1,55 @@
#ifndef DASHBOARDPAGE_H
#define DASHBOARDPAGE_H
#include <QWidget>
#include <QTimer>
#include <QJsonDocument>
#include <QJsonObject>
#include <QJsonArray>
#include <QDesktopServices>
#include <QtConcurrent>
#include <Managers/info_manager.h>
#include "circlebar.h"
#include "linebar.h"
namespace Ui {
class DashboardPage;
}
class DashboardPage : public QWidget
{
Q_OBJECT
public:
explicit DashboardPage(QWidget *parent = 0);
~DashboardPage();
private slots:
void init();
void checkUpdate();
void systemInformationInit();
void updateCpuBar();
void updateMemoryBar();
void updateDiskBar();
void updateNetworkBar();
void on_downloadUpdateBtn_clicked();
private:
Ui::DashboardPage *ui;
private:
CircleBar* cpuBar;
CircleBar* memBar;
CircleBar* diskBar;
LineBar *downloadBar;
LineBar *uploadBar;
QTimer *timer;
InfoManager *im;
};
#endif // DASHBOARDPAGE_H

View File

@@ -0,0 +1,264 @@
<?xml version="1.0" encoding="UTF-8"?>
<ui version="4.0">
<class>DashboardPage</class>
<widget class="QWidget" name="DashboardPage">
<property name="geometry">
<rect>
<x>0</x>
<y>0</y>
<width>811</width>
<height>565</height>
</rect>
</property>
<property name="sizePolicy">
<sizepolicy hsizetype="Expanding" vsizetype="Expanding">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="windowTitle">
<string notr="true">Form</string>
</property>
<layout class="QGridLayout" name="gridLayout">
<property name="leftMargin">
<number>20</number>
</property>
<property name="topMargin">
<number>10</number>
</property>
<property name="rightMargin">
<number>20</number>
</property>
<property name="bottomMargin">
<number>10</number>
</property>
<property name="spacing">
<number>10</number>
</property>
<item row="2" column="1">
<widget class="QWidget" name="lineBars" native="true">
<property name="sizePolicy">
<sizepolicy hsizetype="Expanding" vsizetype="Expanding">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="minimumSize">
<size>
<width>150</width>
<height>0</height>
</size>
</property>
<layout class="QVBoxLayout" name="lineBarsLayout">
<property name="spacing">
<number>20</number>
</property>
<property name="leftMargin">
<number>0</number>
</property>
<property name="topMargin">
<number>10</number>
</property>
<property name="rightMargin">
<number>0</number>
</property>
<property name="bottomMargin">
<number>0</number>
</property>
</layout>
</widget>
</item>
<item row="0" column="0" colspan="2">
<widget class="QWidget" name="circleBars" native="true">
<property name="sizePolicy">
<sizepolicy hsizetype="Expanding" vsizetype="Expanding">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="minimumSize">
<size>
<width>0</width>
<height>200</height>
</size>
</property>
<layout class="QHBoxLayout" name="circleBarsLayout">
<property name="spacing">
<number>25</number>
</property>
<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>
</layout>
</widget>
</item>
<item row="2" column="0">
<widget class="QWidget" name="systemInfo" native="true">
<property name="sizePolicy">
<sizepolicy hsizetype="Expanding" vsizetype="Expanding">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="minimumSize">
<size>
<width>200</width>
<height>0</height>
</size>
</property>
<property name="focusPolicy">
<enum>Qt::WheelFocus</enum>
</property>
<layout class="QVBoxLayout" name="verticalLayout">
<property name="spacing">
<number>10</number>
</property>
<property name="leftMargin">
<number>10</number>
</property>
<property name="topMargin">
<number>0</number>
</property>
<property name="rightMargin">
<number>10</number>
</property>
<property name="bottomMargin">
<number>0</number>
</property>
<item>
<spacer name="verticalSpacer_2">
<property name="orientation">
<enum>Qt::Vertical</enum>
</property>
<property name="sizeHint" stdset="0">
<size>
<width>20</width>
<height>20</height>
</size>
</property>
</spacer>
</item>
<item>
<widget class="QLabel" name="systemInfoTitle">
<property name="text">
<string>SYSTEM INFO</string>
</property>
</widget>
</item>
<item>
<widget class="QListView" name="systemInfoList">
<property name="focusPolicy">
<enum>Qt::NoFocus</enum>
</property>
<property name="verticalScrollBarPolicy">
<enum>Qt::ScrollBarAlwaysOff</enum>
</property>
<property name="horizontalScrollBarPolicy">
<enum>Qt::ScrollBarAlwaysOff</enum>
</property>
<property name="autoScroll">
<bool>false</bool>
</property>
<property name="editTriggers">
<set>QAbstractItemView::NoEditTriggers</set>
</property>
<property name="selectionMode">
<enum>QAbstractItemView::NoSelection</enum>
</property>
<property name="selectionBehavior">
<enum>QAbstractItemView::SelectRows</enum>
</property>
<property name="spacing">
<number>5</number>
</property>
<property name="wordWrap">
<bool>true</bool>
</property>
</widget>
</item>
<item>
<spacer name="verticalSpacer">
<property name="orientation">
<enum>Qt::Vertical</enum>
</property>
<property name="sizeHint" stdset="0">
<size>
<width>20</width>
<height>0</height>
</size>
</property>
</spacer>
</item>
</layout>
</widget>
</item>
<item row="3" column="0" colspan="2">
<widget class="QWidget" name="updateBarWidget" native="true">
<property name="sizePolicy">
<sizepolicy hsizetype="Expanding" vsizetype="Fixed">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="minimumSize">
<size>
<width>0</width>
<height>30</height>
</size>
</property>
<property name="styleSheet">
<string notr="true"/>
</property>
<layout class="QHBoxLayout" name="updateBarLayout">
<property name="spacing">
<number>0</number>
</property>
<property name="leftMargin">
<number>15</number>
</property>
<property name="topMargin">
<number>0</number>
</property>
<property name="rightMargin">
<number>5</number>
</property>
<property name="bottomMargin">
<number>0</number>
</property>
<item alignment="Qt::AlignLeft|Qt::AlignVCenter">
<widget class="QLabel" name="updateBarTextLabel">
<property name="text">
<string>There are update currently available.</string>
</property>
</widget>
</item>
<item alignment="Qt::AlignRight|Qt::AlignVCenter">
<widget class="QPushButton" name="downloadUpdateBtn">
<property name="cursor">
<cursorShape>PointingHandCursor</cursorShape>
</property>
<property name="focusPolicy">
<enum>Qt::NoFocus</enum>
</property>
<property name="text">
<string>Download</string>
</property>
</widget>
</item>
</layout>
</widget>
</item>
</layout>
</widget>
<resources/>
<connections/>
</ui>

View File

@@ -0,0 +1,23 @@
#include "linebar.h"
#include "ui_linebar.h"
LineBar::~LineBar()
{
delete ui;
}
LineBar::LineBar(QString title, QWidget *parent) :
QWidget(parent),
ui(new Ui::LineBar)
{
ui->setupUi(this);
ui->lineChartTitle->setText(title);
}
void LineBar::setValue(int value, QString text, QString totalText)
{
ui->lineChartProgress->setValue(value);
ui->lineChartValue->setText(text);
ui->lineChartTotal->setText(totalText);
}

View File

@@ -0,0 +1,24 @@
#ifndef LINEBAR_H
#define LINEBAR_H
#include <QWidget>
namespace Ui {
class LineBar;
}
class LineBar : public QWidget
{
Q_OBJECT
public:
explicit LineBar(QString title, QWidget *parent = 0);
~LineBar();
public slots:
void setValue(int value, QString text, QString totalText);
private:
Ui::LineBar *ui;
};
#endif // LINEBAR_H

View File

@@ -0,0 +1,167 @@
<?xml version="1.0" encoding="UTF-8"?>
<ui version="4.0">
<class>LineBar</class>
<widget class="QWidget" name="LineBar">
<property name="geometry">
<rect>
<x>0</x>
<y>0</y>
<width>474</width>
<height>110</height>
</rect>
</property>
<property name="windowTitle">
<string notr="true"/>
</property>
<layout class="QVBoxLayout" name="verticalLayout_2">
<property name="spacing">
<number>0</number>
</property>
<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="QWidget" name="lineChartWidget" native="true">
<layout class="QGridLayout" name="gridLayout_2">
<property name="leftMargin">
<number>25</number>
</property>
<property name="topMargin">
<number>0</number>
</property>
<property name="rightMargin">
<number>25</number>
</property>
<property name="bottomMargin">
<number>0</number>
</property>
<property name="spacing">
<number>0</number>
</property>
<item row="6" column="0" alignment="Qt::AlignLeft">
<widget class="QLabel" name="lineChartTotal">
<property name="text">
<string notr="true">Total</string>
</property>
</widget>
</item>
<item row="7" column="0" colspan="2">
<spacer name="verticalSpacer_4">
<property name="orientation">
<enum>Qt::Vertical</enum>
</property>
<property name="sizeType">
<enum>QSizePolicy::Expanding</enum>
</property>
<property name="sizeHint" stdset="0">
<size>
<width>1</width>
<height>15</height>
</size>
</property>
</spacer>
</item>
<item row="1" column="0" colspan="2">
<spacer name="verticalSpacer_3">
<property name="orientation">
<enum>Qt::Vertical</enum>
</property>
<property name="sizeType">
<enum>QSizePolicy::Expanding</enum>
</property>
<property name="sizeHint" stdset="0">
<size>
<width>1</width>
<height>15</height>
</size>
</property>
</spacer>
</item>
<item row="4" column="0" colspan="2">
<widget class="QProgressBar" name="lineChartProgress">
<property name="minimumSize">
<size>
<width>0</width>
<height>20</height>
</size>
</property>
<property name="maximumSize">
<size>
<width>16777215</width>
<height>20</height>
</size>
</property>
<property name="styleSheet">
<string notr="true"/>
</property>
<property name="value">
<number>0</number>
</property>
<property name="textVisible">
<bool>false</bool>
</property>
</widget>
</item>
<item row="3" column="0" colspan="2">
<spacer name="verticalSpacer">
<property name="orientation">
<enum>Qt::Vertical</enum>
</property>
<property name="sizeType">
<enum>QSizePolicy::Expanding</enum>
</property>
<property name="sizeHint" stdset="0">
<size>
<width>1</width>
<height>15</height>
</size>
</property>
</spacer>
</item>
<item row="2" column="0" colspan="2">
<widget class="QLabel" name="lineChartTitle">
<property name="text">
<string notr="true">Title</string>
</property>
</widget>
</item>
<item row="5" column="0" colspan="2">
<spacer name="verticalSpacer_2">
<property name="orientation">
<enum>Qt::Vertical</enum>
</property>
<property name="sizeType">
<enum>QSizePolicy::Expanding</enum>
</property>
<property name="sizeHint" stdset="0">
<size>
<width>1</width>
<height>15</height>
</size>
</property>
</spacer>
</item>
<item row="6" column="1" alignment="Qt::AlignRight">
<widget class="QLabel" name="lineChartValue">
<property name="text">
<string notr="true">Value</string>
</property>
</widget>
</item>
</layout>
</widget>
</item>
</layout>
</widget>
<resources/>
<connections/>
</ui>

View File

@@ -0,0 +1,229 @@
#include "processes_page.h"
#include "ui_processes_page.h"
ProcessesPage::~ProcessesPage()
{
delete ui;
delete model;
delete sortModel;
delete timer;
}
ProcessesPage::ProcessesPage(QWidget *parent) :
QWidget(parent),
model(new QStandardItemModel(this)),
sortModel(new QSortFilterProxyModel(this)),
im(InfoManager::ins()),
timer(new QTimer(this)),
ui(new Ui::ProcessesPage)
{
ui->setupUi(this);
init();
}
void ProcessesPage::init()
{
// slider settings
ui->refreshSlider->setRange(1, 10);
ui->refreshSlider->setPageStep(1);
ui->refreshSlider->setSingleStep(1);
// Table settings
sortModel->setSourceModel(model);
headers << "PID" << tr("Resident Memory") << tr("%Memory") << tr("Virtual Memory") << tr("User") << "%CPU"
<< tr("Start Time") << tr("State") << tr("Group") << tr("Nice") << tr("CPU Time")
<< tr("Session") << tr("Seat") << tr("Process");
model->setHorizontalHeaderLabels(headers);
ui->processTable->setModel(sortModel);
sortModel->setSortRole(1);
sortModel->setDynamicSortFilter(true);
sortModel->sort(5, Qt::SortOrder::DescendingOrder);
ui->processTable->horizontalHeader()->setSectionsMovable(true);
ui->processTable->horizontalHeader()->setFixedHeight(36);
ui->processTable->horizontalHeader()->setDefaultAlignment(Qt::AlignLeft | Qt::AlignVCenter);
ui->processTable->horizontalHeader()->setCursor(Qt::PointingHandCursor);
ui->processTable->horizontalHeader()->resizeSection(0, 70);
loadProcesses();
connect(timer, &QTimer::timeout, this, &ProcessesPage::loadProcesses);
timer->setInterval(1000);
timer->start();
ui->processTable->horizontalHeader()->setContextMenuPolicy(Qt::CustomContextMenu);
connect(ui->processTable->horizontalHeader(), SIGNAL(customContextMenuRequested(const QPoint&)),
this, SLOT(on_processTable_customContextMenuRequested(const QPoint&)));
loadHeaderMenu();
}
void ProcessesPage::loadHeaderMenu()
{
int i = 0;
foreach (QString kolon, headers) {
QAction *action = new QAction(kolon);
action->setCheckable(true);
action->setChecked(true);
action->setData(i++);
headerMenu.addAction(action);
}
QList<int> hiddenHeaders = { 6, 7, 8, 9, 10, 11, 12 };
foreach (int i, hiddenHeaders) {
ui->processTable->horizontalHeader()->setSectionHidden(i, true);
headerMenu.actions().at(i)->setChecked(false);
}
}
void ProcessesPage::loadProcesses()
{
QModelIndexList selecteds = ui->processTable->selectionModel()->selectedRows();
model->removeRows(0, model->rowCount());
im->updateProcesses();
foreach (Process proc, im->getProcesses()) {
if (ui->allProcessesCheck->isChecked()) {
model->appendRow(createRow(proc));
}
else {
if (im->getUserName() == proc.getUname())
model->appendRow(createRow(proc));
}
}
ui->processTitleLbl->setText(tr("Processes (%1)").arg(model->rowCount()));
// selected item
if(! selecteds.isEmpty()) {
seletedRowModel = selecteds.first();
for (int i = 0; i < sortModel->rowCount(); ++i) {
if (sortModel->index(i, 0).data(1).toInt() == seletedRowModel.data(1).toInt())
ui->processTable->selectRow(i);
}
} else {
seletedRowModel = QModelIndex();
}
}
QList<QStandardItem*> ProcessesPage::createRow(Process proc)
{
QList<QStandardItem*> row;
int data = 1;
QStandardItem *pid_i = new QStandardItem(QString::number(proc.getPid()));
pid_i->setData(proc.getPid(), data);
pid_i->setData(proc.getPid(), Qt::ToolTipRole);
QStandardItem *rss_i = new QStandardItem(FormatUtil::formatBytes(proc.getRss()));
rss_i->setData(proc.getRss(), data);
rss_i->setData(FormatUtil::formatBytes(proc.getRss()), Qt::ToolTipRole);
QStandardItem *pmem_i = new QStandardItem(QString::number(proc.getPmem()));
pmem_i->setData(proc.getPmem(), data);
pmem_i->setData(proc.getPmem(), Qt::ToolTipRole);
QStandardItem *vsize_i = new QStandardItem(FormatUtil::formatBytes(proc.getVsize()));
vsize_i->setData(proc.getVsize(), data);
vsize_i->setData(FormatUtil::formatBytes(proc.getVsize()), Qt::ToolTipRole);
QStandardItem *uname_i = new QStandardItem(proc.getUname());
uname_i->setData(proc.getUname(), data);
uname_i->setData(proc.getUname(), Qt::ToolTipRole);
QStandardItem *pcpu_i = new QStandardItem(QString::number(proc.getPcpu()));
pcpu_i->setData(proc.getPcpu(), data);
pcpu_i->setData(proc.getPcpu(), Qt::ToolTipRole);
QStandardItem *starttime_i = new QStandardItem(proc.getStartTime());
starttime_i->setData(proc.getStartTime(), data);
starttime_i->setData(proc.getStartTime(), Qt::ToolTipRole);
QStandardItem *state_i = new QStandardItem(proc.getState());
state_i->setData(proc.getState(), data);
state_i->setData(proc.getState(), Qt::ToolTipRole);
QStandardItem *group_i = new QStandardItem(proc.getGroup());
group_i->setData(proc.getGroup(), data);
group_i->setData(proc.getGroup(), Qt::ToolTipRole);
QStandardItem *nice_i = new QStandardItem(QString::number(proc.getNice()));
nice_i->setData(proc.getNice(), data);
nice_i->setData(proc.getNice(), Qt::ToolTipRole);
QStandardItem *cpuTime_i = new QStandardItem(proc.getCpuTime());
cpuTime_i->setData(proc.getCpuTime(), data);
cpuTime_i->setData(proc.getCpuTime(), Qt::ToolTipRole);
QStandardItem *session_i = new QStandardItem(proc.getSession());
session_i->setData(proc.getSession(), data);
session_i->setData(proc.getSession(), Qt::ToolTipRole);
QStandardItem *seat_i = new QStandardItem(proc.getSeat());
seat_i->setData(proc.getSeat(), data);
seat_i->setData(proc.getSeat(), Qt::ToolTipRole);
QStandardItem *cmd_i = new QStandardItem(proc.getCmd());
cmd_i->setData(proc.getCmd(), data);
cmd_i->setData(proc.getCmd(), Qt::ToolTipRole);
row << pid_i << rss_i << pmem_i << vsize_i << uname_i << pcpu_i
<< starttime_i << state_i << group_i << nice_i << cpuTime_i
<< session_i << seat_i<< cmd_i;
return row;
}
void ProcessesPage::on_processSearchBox_textChanged(const QString &val)
{
QRegExp query(val, Qt::CaseInsensitive, QRegExp::Wildcard);
sortModel->setFilterKeyColumn(headers.count() - 1); // process name
sortModel->setFilterRegExp(query);
}
void ProcessesPage::on_refreshSlider_valueChanged(int i)
{
ui->refreshLabel->setText(tr("Refresh (%1)").arg(i));
timer->setInterval(i * 1000);
}
void ProcessesPage::on_endProcessBtn_clicked()
{
pid_t pid = seletedRowModel.data(1).toInt();
QString selectedUname = sortModel->index(seletedRowModel.row(), 4).data(1).toString();
try {
if (pid) {
if (selectedUname == im->getUserName())
CommandUtil::exec("kill", { QString::number(pid) });
else
CommandUtil::sudoExec("kill", { QString::number(pid) });
}
} catch (QString &ex) {
qCritical() << ex;
}
}
void ProcessesPage::on_processTable_customContextMenuRequested(const QPoint &pos)
{
QPoint globalPos = ui->processTable->mapToGlobal(pos);
QAction *action = headerMenu.exec(globalPos);
if (action)
ui->processTable->horizontalHeader()->setSectionHidden(action->data().toInt(),
! action->isChecked());
}

View File

@@ -0,0 +1,50 @@
#ifndef PROCESSESPAGE_H
#define PROCESSESPAGE_H
#include <QWidget>
#include <QStandardItemModel>
#include <QSortFilterProxyModel>
#include <QDebug>
#include <QScrollBar>
#include <QTimer>
#include <QMenu>
#include <QAction>
#include "Managers/info_manager.h"
namespace Ui {
class ProcessesPage;
}
class ProcessesPage : public QWidget
{
Q_OBJECT
public:
explicit ProcessesPage(QWidget *parent = 0);
~ProcessesPage();
private slots:
void init();
void loadProcesses();
QList<QStandardItem *> createRow(Process proc);
void on_processSearchBox_textChanged(const QString &val);
void on_refreshSlider_valueChanged(int i);
void on_endProcessBtn_clicked();
void on_processTable_customContextMenuRequested(const QPoint &pos);
void loadHeaderMenu();
private:
Ui::ProcessesPage *ui;
private:
QStandardItemModel *model;
QSortFilterProxyModel *sortModel;
QModelIndex seletedRowModel;
QStringList headers;
InfoManager *im;
QTimer *timer;
QMenu headerMenu;
};
#endif // PROCESSESPAGE_H

View File

@@ -0,0 +1,217 @@
<?xml version="1.0" encoding="UTF-8"?>
<ui version="4.0">
<class>ProcessesPage</class>
<widget class="QWidget" name="ProcessesPage">
<property name="geometry">
<rect>
<x>0</x>
<y>0</y>
<width>835</width>
<height>612</height>
</rect>
</property>
<property name="windowTitle">
<string notr="true"/>
</property>
<property name="styleSheet">
<string notr="true"/>
</property>
<layout class="QGridLayout" name="gridLayout">
<property name="leftMargin">
<number>20</number>
</property>
<property name="topMargin">
<number>5</number>
</property>
<property name="rightMargin">
<number>20</number>
</property>
<property name="bottomMargin">
<number>20</number>
</property>
<property name="horizontalSpacing">
<number>0</number>
</property>
<property name="verticalSpacing">
<number>5</number>
</property>
<item row="1" column="0">
<layout class="QHBoxLayout" name="topLayout">
<property name="spacing">
<number>10</number>
</property>
<property name="leftMargin">
<number>5</number>
</property>
<property name="topMargin">
<number>0</number>
</property>
<property name="rightMargin">
<number>10</number>
</property>
<item>
<widget class="QLabel" name="processTitleLbl">
<property name="text">
<string>Processes</string>
</property>
</widget>
</item>
<item>
<widget class="QCheckBox" name="allProcessesCheck">
<property name="cursor">
<cursorShape>PointingHandCursor</cursorShape>
</property>
<property name="focusPolicy">
<enum>Qt::NoFocus</enum>
</property>
<property name="text">
<string>All Processes</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>
<item alignment="Qt::AlignRight">
<widget class="QLineEdit" name="processSearchBox">
<property name="placeholderText">
<string>Search...</string>
</property>
<property name="clearButtonEnabled">
<bool>true</bool>
</property>
</widget>
</item>
</layout>
</item>
<item row="3" column="0">
<widget class="QTableView" name="processTable">
<property name="focusPolicy">
<enum>Qt::NoFocus</enum>
</property>
<property name="frameShape">
<enum>QFrame::NoFrame</enum>
</property>
<property name="frameShadow">
<enum>QFrame::Sunken</enum>
</property>
<property name="sizeAdjustPolicy">
<enum>QAbstractScrollArea::AdjustToContents</enum>
</property>
<property name="editTriggers">
<set>QAbstractItemView::NoEditTriggers</set>
</property>
<property name="selectionMode">
<enum>QAbstractItemView::SingleSelection</enum>
</property>
<property name="selectionBehavior">
<enum>QAbstractItemView::SelectRows</enum>
</property>
<property name="textElideMode">
<enum>Qt::ElideMiddle</enum>
</property>
<property name="gridStyle">
<enum>Qt::SolidLine</enum>
</property>
<property name="sortingEnabled">
<bool>true</bool>
</property>
<property name="wordWrap">
<bool>true</bool>
</property>
<attribute name="horizontalHeaderCascadingSectionResizes">
<bool>false</bool>
</attribute>
<attribute name="horizontalHeaderStretchLastSection">
<bool>true</bool>
</attribute>
<attribute name="verticalHeaderVisible">
<bool>false</bool>
</attribute>
</widget>
</item>
<item row="4" column="0">
<widget class="QWidget" name="bottomWidget" native="true">
<layout class="QHBoxLayout" name="bottomLayout">
<property name="spacing">
<number>10</number>
</property>
<property name="leftMargin">
<number>0</number>
</property>
<property name="topMargin">
<number>5</number>
</property>
<property name="rightMargin">
<number>0</number>
</property>
<property name="bottomMargin">
<number>0</number>
</property>
<item alignment="Qt::AlignLeft|Qt::AlignVCenter">
<widget class="QLabel" name="refreshLabel">
<property name="text">
<string notr="true">Refresh (1)</string>
</property>
</widget>
</item>
<item alignment="Qt::AlignLeft|Qt::AlignVCenter">
<widget class="QSlider" name="refreshSlider">
<property name="cursor">
<cursorShape>PointingHandCursor</cursorShape>
</property>
<property name="focusPolicy">
<enum>Qt::NoFocus</enum>
</property>
<property name="styleSheet">
<string notr="true"/>
</property>
<property name="orientation">
<enum>Qt::Horizontal</enum>
</property>
</widget>
</item>
<item>
<spacer name="horizontalSpacer_2">
<property name="orientation">
<enum>Qt::Horizontal</enum>
</property>
<property name="sizeHint" stdset="0">
<size>
<width>40</width>
<height>20</height>
</size>
</property>
</spacer>
</item>
<item>
<widget class="QPushButton" name="endProcessBtn">
<property name="cursor">
<cursorShape>PointingHandCursor</cursorShape>
</property>
<property name="focusPolicy">
<enum>Qt::NoFocus</enum>
</property>
<property name="text">
<string>End Process</string>
</property>
</widget>
</item>
</layout>
</widget>
</item>
</layout>
</widget>
<resources/>
<connections/>
</ui>

View File

@@ -0,0 +1,103 @@
#include "history_chart.h"
#include "ui_history_chart.h"
HistoryChart::~HistoryChart()
{
delete ui;
delete chart;
delete chartView;
}
HistoryChart::HistoryChart(QString title, int seriesCount, QWidget *parent) :
QWidget(parent),
title(title),
yMax(0),
seriesCount(seriesCount),
chartView(new QChartView),
chart(chartView->chart()),
apm(AppManager::ins()),
ui(new Ui::HistoryChart)
{
ui->setupUi(this);
init();
}
void HistoryChart::init()
{
ui->historyTitle->setText(title);
// create lists
for (int i = 0; i < seriesCount; i++)
seriesList.append(new QLineSeries);
// add series to chart
for (int i = 0; i < seriesList.count(); ++i)
chart->addSeries(seriesList.at(i));
chartView->setRenderHint(QPainter::Antialiasing);
QList<int> colors = {
0x2ecc71, 0xe74c3c, 0x3498db, 0xf1c40f, 0xe67e22,
0x1abc9c, 0x9b59b6, 0x34495e, 0xd35400, 0xc0392b,
0x8e44ad, 0xFF8F00, 0xEF6C00, 0x4E342E, 0x424242,
0x5499C7, 0x58D68D, 0xCD6155, 0xF5B041, 0x566573
};
// set colors
for (int i = 0; i < seriesList.count(); ++i)
seriesList.at(i)->setColor(QColor(colors.at(i)));
// Chart Settings
chart->createDefaultAxes();
chart->axisX()->setRange(0, 60);
chart->axisX()->setReverse(true);
chart->setContentsMargins(-11, -11, -11, -11);
chart->setMargins(QMargins(20, 0, 10, 10));
ui->verticalLayout->addWidget(chartView);
// theme changed
connect(AppManager::ins(), &AppManager::changedTheme, this, [this]() {
chart->axisX()->setLabelsColor(apm->getStyleValues()->value("@chartLabelColor").toString());
chart->axisX()->setGridLineColor(apm->getStyleValues()->value("@chartGridColor").toString());
chart->axisY()->setLabelsColor(apm->getStyleValues()->value("@chartLabelColor").toString());
chart->axisY()->setGridLineColor(apm->getStyleValues()->value("@chartGridColor").toString());
chart->setBackgroundBrush(QColor(apm->getStyleValues()->value("@historyChartBackgroundColor").toString()));
chart->legend()->setLabelColor(apm->getStyleValues()->value("@chartLabelColor").toString());
});
}
void HistoryChart::setYMax(int value)
{
yMax = value;
}
QVector<QLineSeries *> HistoryChart::getSeriesList() const
{
return seriesList;
}
void HistoryChart::setSeriesList(QVector<QLineSeries *> &value)
{
seriesList = value;
for (int i = 0; i < seriesList.count(); ++i)
chart->series().replace(0, seriesList.at(i));
if(yMax) chart->axisY()->setRange(0, yMax);
chartView->repaint();
}
void HistoryChart::on_historyTitle_clicked(bool checked)
{
QLayout *charts = topLevelWidget()->findChild<QWidget*>("charts")->layout();
for (int i = 0; i < charts->count(); ++i)
charts->itemAt(i)->widget()->setVisible(! checked);
show();
}

View File

@@ -0,0 +1,46 @@
#ifndef HISTORYCHART_H
#define HISTORYCHART_H
#include <QWidget>
#include <QDebug>
#include <QtCharts>
#include <QTimer>
#include "Managers/app_manager.h"
namespace Ui {
class HistoryChart;
}
class HistoryChart : public QWidget
{
Q_OBJECT
public:
explicit HistoryChart(QString title, int seriesCount, QWidget *parent = 0);
~HistoryChart();
QVector<QLineSeries *> getSeriesList() const;
public slots:
void setYMax(int value);
void setSeriesList(QVector<QLineSeries *> &value);
private slots:
void init();
void on_historyTitle_clicked(bool checked);
private:
Ui::HistoryChart *ui;
private:
QString title;
int yMax;
int seriesCount;
QChartView *chartView;
QChart *chart;
QVector<QLineSeries *> seriesList;
AppManager *apm;
};
#endif // HISTORYCHART_H

View File

@@ -0,0 +1,52 @@
<?xml version="1.0" encoding="UTF-8"?>
<ui version="4.0">
<class>HistoryChart</class>
<widget class="QWidget" name="HistoryChart">
<property name="geometry">
<rect>
<x>0</x>
<y>0</y>
<width>930</width>
<height>387</height>
</rect>
</property>
<property name="windowTitle">
<string notr="true"/>
</property>
<layout class="QVBoxLayout" name="verticalLayout">
<property name="spacing">
<number>0</number>
</property>
<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 alignment="Qt::AlignLeft">
<widget class="QCheckBox" name="historyTitle">
<property name="cursor">
<cursorShape>PointingHandCursor</cursorShape>
</property>
<property name="focusPolicy">
<enum>Qt::NoFocus</enum>
</property>
<property name="styleSheet">
<string notr="true"/>
</property>
<property name="text">
<string notr="true">Chart Title</string>
</property>
</widget>
</item>
</layout>
</widget>
<resources/>
<connections/>
</ui>

View File

@@ -0,0 +1,165 @@
#include "resources_page.h"
#include "ui_resources_page.h"
ResourcesPage::~ResourcesPage()
{
delete ui;
delete cpuChart;
delete memoryChart;
delete networkChart;
delete timer;
}
ResourcesPage::ResourcesPage(QWidget *parent) :
QWidget(parent),
timer(new QTimer),
im(InfoManager::ins()),
ui(new Ui::ResourcesPage)
{
ui->setupUi(this);
init();
}
void ResourcesPage::init()
{
cpuChart = new HistoryChart(tr("CPU History"), im->getCpuCoreCount());
cpuChart->setYMax(100);
memoryChart = new HistoryChart(tr("Memory History"), 2);
memoryChart->setYMax(100);
networkChart = new HistoryChart(tr("Network History"), 2);
ui->chartsLayout->addWidget(cpuChart);
ui->chartsLayout->addWidget(memoryChart);
ui->chartsLayout->addWidget(networkChart);
connect(timer, &QTimer::timeout, this, &ResourcesPage::updateCpuChart);
connect(timer, &QTimer::timeout, this, &ResourcesPage::updateMemoryChart);
connect(timer, &QTimer::timeout, this, &ResourcesPage::updateNetworkChart);
timer->start(1 * 1000);
}
void ResourcesPage::updateNetworkChart()
{
static int second = 0;
QVector<QLineSeries *> seriesList = networkChart->getSeriesList();
// points swap
for (int j = 0; j < seriesList.count(); j++) {
for (int i = 0; i < (second < 61 ? second : 61); i++)
seriesList.at(j)->replace(i, (i+1), seriesList.at(j)->at(i).y());
if(second > 61)
seriesList.at(j)->removePoints(61, 1);
}
static quint64 l_RXbytes = im->getRXbytes();
static quint64 l_TXbytes = im->getTXbytes();
static quint64 max_RXbytes = 1L << 20; // 1 MEBI
static quint64 max_TXbytes = 1L << 20; // 1 MEBI
quint64 RXbytes = im->getRXbytes();
quint64 TXbytes = im->getTXbytes();
quint64 d_RXbytes = (RXbytes - l_RXbytes);
quint64 d_TXbytes = (TXbytes - l_TXbytes);
QString downText = FormatUtil::formatBytes(d_RXbytes);
QString upText = FormatUtil::formatBytes(d_TXbytes);
// Download
seriesList.at(0)->insert(0, QPointF(0, d_RXbytes >> 10));
seriesList.at(0)->setName(tr("Download %1/s Total: %2")
.arg(downText)
.arg(FormatUtil::formatBytes(RXbytes)));
seriesList.at(1)->insert(0, QPointF(0, d_TXbytes >> 10));
seriesList.at(1)->setName(tr("Upload %1/s Total: %2")
.arg(upText)
.arg(FormatUtil::formatBytes(TXbytes)));
max_RXbytes = qMax(max_RXbytes, d_RXbytes);
max_TXbytes = qMax(max_TXbytes, d_TXbytes);
int max = qMax(max_RXbytes, max_TXbytes) >> 10;
networkChart->setYMax(max);
l_RXbytes = RXbytes;
l_TXbytes = TXbytes;
second++;
networkChart->setSeriesList(seriesList);
}
void ResourcesPage::updateMemoryChart()
{
static int second = 0;
QVector<QLineSeries *> seriesList = memoryChart->getSeriesList();
im->updateMemoryInfo();
// points swap
for (int j = 0; j < seriesList.count(); j++) {
for (int i = 0; i < (second < 61 ? second : 61); i++)
seriesList.at(j)->replace(i, (i+1), seriesList.at(j)->at(i).y());
if(second > 61)
seriesList.at(j)->removePoints(61, 1);
}
// Swap
double percent = 0;
if (im->getSwapTotal()) // aritmetic exception control
percent = ((double) im->getSwapUsed() / (double) im->getSwapTotal()) * 100.0;
seriesList.at(0)->insert(0, QPointF(0, percent));
seriesList.at(0)->setName(tr("Swap %1 (%2%) %3")
.arg(FormatUtil::formatBytes(im->getSwapUsed()))
.arg(QString().sprintf("%.1f",percent))
.arg(FormatUtil::formatBytes(im->getSwapTotal())));
// Memory
double percent2 = ((double) im->getMemUsed() / (double) im->getMemTotal()) * 100.0;
seriesList.at(1)->insert(0, QPointF(0, percent2));
seriesList.at(1)->setName(tr("Memory %1 (%2%) %3")
.arg(FormatUtil::formatBytes(im->getMemUsed()))
.arg(QString().sprintf("%.1f",percent2))
.arg(FormatUtil::formatBytes(im->getMemTotal())));
second++;
memoryChart->setSeriesList(seriesList);
}
void ResourcesPage::updateCpuChart()
{
static int second = 0;
QList<int> cpuPercents = im->getCpuPercents();
QVector<QLineSeries *> seriesList = cpuChart->getSeriesList();
for (int j = 0; j < seriesList.count(); j++){
int p = cpuPercents.at(j+1);
for (int i = 0; i < (second < 61 ? second : 61); i++)
seriesList.at(j)->replace(i, (i+1), seriesList.at(j)->at(i).y());
seriesList.at(j)->insert(0, QPointF(0, p));
seriesList.at(j)->setName(QString("CPU%1 %2%").arg(j+1).arg(p));
if(second > 61) seriesList.at(j)->removePoints(61, 1);
}
second++;
cpuChart->setSeriesList(seriesList);
}

View File

@@ -0,0 +1,40 @@
#ifndef RESOURCESPAGE_H
#define RESOURCESPAGE_H
#include <QWidget>
#include <QTimer>
#include "history_chart.h"
#include "Managers/info_manager.h"
namespace Ui {
class ResourcesPage;
}
class ResourcesPage : public QWidget
{
Q_OBJECT
public:
explicit ResourcesPage(QWidget *parent = 0);
~ResourcesPage();
private slots:
void updateCpuChart();
void updateMemoryChart();
void updateNetworkChart();
private:
Ui::ResourcesPage *ui;
void init();
private:
HistoryChart *cpuChart;
HistoryChart *memoryChart;
HistoryChart *networkChart;
QTimer *timer;
InfoManager *im;
};
#endif // RESOURCESPAGE_H

View File

@@ -0,0 +1,57 @@
<?xml version="1.0" encoding="UTF-8"?>
<ui version="4.0">
<class>ResourcesPage</class>
<widget class="QWidget" name="ResourcesPage">
<property name="geometry">
<rect>
<x>0</x>
<y>0</y>
<width>890</width>
<height>537</height>
</rect>
</property>
<property name="windowTitle">
<string notr="true"/>
</property>
<layout class="QVBoxLayout" name="verticalLayout">
<property name="spacing">
<number>0</number>
</property>
<property name="leftMargin">
<number>10</number>
</property>
<property name="topMargin">
<number>10</number>
</property>
<property name="rightMargin">
<number>10</number>
</property>
<property name="bottomMargin">
<number>1</number>
</property>
<item>
<widget class="QWidget" name="charts" native="true">
<layout class="QVBoxLayout" name="chartsLayout">
<property name="spacing">
<number>10</number>
</property>
<property name="leftMargin">
<number>10</number>
</property>
<property name="topMargin">
<number>0</number>
</property>
<property name="rightMargin">
<number>10</number>
</property>
<property name="bottomMargin">
<number>10</number>
</property>
</layout>
</widget>
</item>
</layout>
</widget>
<resources/>
<connections/>
</ui>

View File

@@ -0,0 +1,37 @@
#include "service_item.h"
#include "ui_service_item.h"
ServiceItem::~ServiceItem()
{
delete ui;
}
ServiceItem::ServiceItem(QString name, bool status, bool active, QWidget *parent) :
QWidget(parent),
name(name),
tm(ToolManager::ins()),
ui(new Ui::ServiceItem)
{
ui->setupUi(this);
ui->serviceName->setText(name);
ui->runningBtn->setChecked(active);
ui->startupBtn->setChecked(status);
connect(ui->startupBtn, &QCheckBox::clicked, this, &ServiceItem::startupBtn_toggled);
connect(ui->runningBtn, &QCheckBox::clicked, this, &ServiceItem::runningBtn_toggled);
}
void ServiceItem::startupBtn_toggled(bool status)
{
tm->changeServiceStatus(ui->serviceName->text(), status);
ui->startupBtn->setChecked(tm->serviceIsEnabled(name));
}
void ServiceItem::runningBtn_toggled(bool status)
{
tm->changeServiceActive(ui->serviceName->text(), status);
ui->runningBtn->setChecked(tm->serviceIsActive(name));
}

View File

@@ -0,0 +1,33 @@
#ifndef SERVICE_ITEM_H
#define SERVICE_ITEM_H
#include <QWidget>
#include <QDebug>
#include "Managers/tool_manager.h"
namespace Ui {
class ServiceItem;
}
class ServiceItem : public QWidget
{
Q_OBJECT
public:
explicit ServiceItem(QString name, bool status, bool active, QWidget *parent = 0);
~ServiceItem();
private slots:
void runningBtn_toggled(bool status);
void startupBtn_toggled(bool status);
private:
Ui::ServiceItem *ui;
private:
QString name;
ToolManager *tm;
};
#endif // SERVICE_ITEM_H

View File

@@ -0,0 +1,171 @@
<?xml version="1.0" encoding="UTF-8"?>
<ui version="4.0">
<class>ServiceItem</class>
<widget class="QWidget" name="ServiceItem">
<property name="geometry">
<rect>
<x>0</x>
<y>0</y>
<width>713</width>
<height>45</height>
</rect>
</property>
<property name="sizePolicy">
<sizepolicy hsizetype="Preferred" vsizetype="Expanding">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="minimumSize">
<size>
<width>0</width>
<height>45</height>
</size>
</property>
<property name="maximumSize">
<size>
<width>16777215</width>
<height>45</height>
</size>
</property>
<property name="cursor">
<cursorShape>ArrowCursor</cursorShape>
</property>
<property name="windowTitle">
<string notr="true"/>
</property>
<layout class="QGridLayout" name="gridLayout">
<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>
<property name="spacing">
<number>0</number>
</property>
<item row="0" column="1" alignment="Qt::AlignTop">
<widget class="QWidget" name="serviceItemWidget" native="true">
<property name="minimumSize">
<size>
<width>0</width>
<height>45</height>
</size>
</property>
<property name="maximumSize">
<size>
<width>16777215</width>
<height>45</height>
</size>
</property>
<layout class="QGridLayout" name="serviceItemLayout">
<property name="leftMargin">
<number>15</number>
</property>
<property name="rightMargin">
<number>10</number>
</property>
<property name="horizontalSpacing">
<number>10</number>
</property>
<property name="verticalSpacing">
<number>0</number>
</property>
<item row="0" column="3">
<widget class="QCheckBox" name="startupBtn">
<property name="cursor">
<cursorShape>PointingHandCursor</cursorShape>
</property>
<property name="focusPolicy">
<enum>Qt::NoFocus</enum>
</property>
<property name="text">
<string/>
</property>
</widget>
</item>
<item row="0" column="4">
<spacer name="horizontalSpacer_2">
<property name="orientation">
<enum>Qt::Horizontal</enum>
</property>
<property name="sizeType">
<enum>QSizePolicy::Fixed</enum>
</property>
<property name="sizeHint" stdset="0">
<size>
<width>60</width>
<height>0</height>
</size>
</property>
</spacer>
</item>
<item row="0" column="0">
<widget class="QLabel" name="serviceIcon">
<property name="minimumSize">
<size>
<width>25</width>
<height>25</height>
</size>
</property>
<property name="maximumSize">
<size>
<width>25</width>
<height>25</height>
</size>
</property>
<property name="text">
<string/>
</property>
<property name="scaledContents">
<bool>true</bool>
</property>
</widget>
</item>
<item row="0" column="1">
<widget class="QLabel" name="serviceName">
<property name="text">
<string notr="true">Service Name</string>
</property>
</widget>
</item>
<item row="0" column="2">
<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>
<item row="0" column="5">
<widget class="QCheckBox" name="runningBtn">
<property name="cursor">
<cursorShape>PointingHandCursor</cursorShape>
</property>
<property name="focusPolicy">
<enum>Qt::NoFocus</enum>
</property>
<property name="text">
<string/>
</property>
</widget>
</item>
</layout>
</widget>
</item>
</layout>
</widget>
<resources/>
<connections/>
</ui>

View File

@@ -0,0 +1,52 @@
#include "services_page.h"
#include "ui_services_page.h"
ServicesPage::~ServicesPage()
{
delete ui;
}
ServicesPage::ServicesPage(QWidget *parent) :
QWidget(parent),
tm(ToolManager::ins()),
ui(new Ui::ServicesPage)
{
ui->setupUi(this);
init();
}
void ServicesPage::init()
{
loadServices();
if(ui->serviceListWidget->count()) {
ui->notFoundWidget->hide();
}
else { // list widget is empty show not found
ui->notFoundWidget->show();
ui->serviceListWidget->hide();
}
}
void ServicesPage::loadServices()
{
foreach (Service s, tm->getServices()) {
ServiceItem *service = new ServiceItem(s.name, s.status, s.active, this);
QListWidgetItem *item = new QListWidgetItem(ui->serviceListWidget);
item->setSizeHint(service->sizeHint());
ui->serviceListWidget->setItemWidget(item, service);
}
setAppCount();
}
void ServicesPage::setAppCount()
{
ui->servicesTitle->setText(tr("System Services (%1)")
.arg(ui->serviceListWidget->count()));
}

View File

@@ -0,0 +1,36 @@
#ifndef SERVICESPAGE_H
#define SERVICESPAGE_H
#include <QWidget>
#include <QDebug>
#include <QtConcurrent>
#include "service_item.h"
#include "Managers/tool_manager.h"
namespace Ui {
class ServicesPage;
}
class ServicesPage : public QWidget
{
Q_OBJECT
public:
explicit ServicesPage(QWidget *parent = 0);
~ServicesPage();
private slots:
void init();
void loadServices();
public slots:
void setAppCount();
private:
Ui::ServicesPage *ui;
private:
ToolManager *tm;
};
#endif // SERVICESPAGE_H

View File

@@ -0,0 +1,304 @@
<?xml version="1.0" encoding="UTF-8"?>
<ui version="4.0">
<class>ServicesPage</class>
<widget class="QWidget" name="ServicesPage">
<property name="geometry">
<rect>
<x>0</x>
<y>0</y>
<width>882</width>
<height>549</height>
</rect>
</property>
<property name="windowTitle">
<string notr="true"/>
</property>
<layout class="QVBoxLayout" name="verticalLayout_2">
<property name="spacing">
<number>0</number>
</property>
<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="QWidget" name="verticalWidget" native="true">
<property name="styleSheet">
<string notr="true"/>
</property>
<layout class="QVBoxLayout" name="verticalLayout">
<property name="spacing">
<number>0</number>
</property>
<property name="leftMargin">
<number>30</number>
</property>
<property name="topMargin">
<number>10</number>
</property>
<property name="rightMargin">
<number>30</number>
</property>
<property name="bottomMargin">
<number>30</number>
</property>
<item>
<layout class="QHBoxLayout" name="titlesLayout">
<property name="spacing">
<number>0</number>
</property>
<property name="leftMargin">
<number>15</number>
</property>
<property name="rightMargin">
<number>45</number>
</property>
<property name="bottomMargin">
<number>0</number>
</property>
<item alignment="Qt::AlignLeft|Qt::AlignVCenter">
<widget class="QLabel" name="servicesTitle">
<property name="font">
<font>
<family>Ubuntu</family>
<pointsize>11</pointsize>
</font>
</property>
<property name="styleSheet">
<string notr="true"/>
</property>
<property name="text">
<string>System Services</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>
<item alignment="Qt::AlignLeft">
<widget class="QLabel" name="serviceStartupImg">
<property name="sizePolicy">
<sizepolicy hsizetype="Fixed" vsizetype="Fixed">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="minimumSize">
<size>
<width>20</width>
<height>20</height>
</size>
</property>
<property name="maximumSize">
<size>
<width>80</width>
<height>16777215</height>
</size>
</property>
<property name="font">
<font>
<family>Ubuntu</family>
<pointsize>10</pointsize>
</font>
</property>
<property name="toolTip">
<string>Startup at boot ?</string>
</property>
<property name="styleSheet">
<string notr="true"/>
</property>
<property name="text">
<string/>
</property>
</widget>
</item>
<item>
<spacer name="horizontalSpacer_2">
<property name="orientation">
<enum>Qt::Horizontal</enum>
</property>
<property name="sizeType">
<enum>QSizePolicy::Fixed</enum>
</property>
<property name="sizeHint" stdset="0">
<size>
<width>100</width>
<height>20</height>
</size>
</property>
</spacer>
</item>
<item alignment="Qt::AlignRight">
<widget class="QLabel" name="systemRunningImg">
<property name="sizePolicy">
<sizepolicy hsizetype="Fixed" vsizetype="Fixed">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="minimumSize">
<size>
<width>20</width>
<height>20</height>
</size>
</property>
<property name="maximumSize">
<size>
<width>100</width>
<height>16777215</height>
</size>
</property>
<property name="font">
<font>
<family>Ubuntu</family>
<pointsize>10</pointsize>
</font>
</property>
<property name="toolTip">
<string>Running Now ?</string>
</property>
<property name="styleSheet">
<string notr="true"/>
</property>
<property name="text">
<string/>
</property>
</widget>
</item>
</layout>
</item>
<item>
<widget class="QWidget" name="notFoundWidget" native="true">
<property name="sizePolicy">
<sizepolicy hsizetype="Preferred" vsizetype="Expanding">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="minimumSize">
<size>
<width>0</width>
<height>200</height>
</size>
</property>
<property name="maximumSize">
<size>
<width>16777215</width>
<height>9999999</height>
</size>
</property>
<property name="styleSheet">
<string notr="true"/>
</property>
<layout class="QVBoxLayout" name="notFoundLayout">
<property name="spacing">
<number>0</number>
</property>
<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>
<spacer name="verticalSpacer_2">
<property name="orientation">
<enum>Qt::Vertical</enum>
</property>
<property name="sizeType">
<enum>QSizePolicy::Fixed</enum>
</property>
<property name="sizeHint" stdset="0">
<size>
<width>20</width>
<height>180</height>
</size>
</property>
</spacer>
</item>
<item alignment="Qt::AlignHCenter|Qt::AlignBottom">
<widget class="QLabel" name="label">
<property name="text">
<string>Not Found System Service</string>
</property>
</widget>
</item>
<item>
<spacer name="verticalSpacer">
<property name="orientation">
<enum>Qt::Vertical</enum>
</property>
<property name="sizeHint" stdset="0">
<size>
<width>20</width>
<height>0</height>
</size>
</property>
</spacer>
</item>
</layout>
</widget>
</item>
<item>
<widget class="QListWidget" name="serviceListWidget">
<property name="focusPolicy">
<enum>Qt::NoFocus</enum>
</property>
<property name="horizontalScrollBarPolicy">
<enum>Qt::ScrollBarAlwaysOff</enum>
</property>
<property name="editTriggers">
<set>QAbstractItemView::NoEditTriggers</set>
</property>
<property name="selectionMode">
<enum>QAbstractItemView::NoSelection</enum>
</property>
<property name="selectionBehavior">
<enum>QAbstractItemView::SelectRows</enum>
</property>
<property name="resizeMode">
<enum>QListView::Adjust</enum>
</property>
<property name="layoutMode">
<enum>QListView::Batched</enum>
</property>
<property name="spacing">
<number>4</number>
</property>
<property name="uniformItemSizes">
<bool>true</bool>
</property>
</widget>
</item>
</layout>
</widget>
</item>
</layout>
</widget>
<resources/>
<connections/>
</ui>

View File

@@ -0,0 +1,60 @@
#include "settings_page.h"
#include "ui_settings_page.h"
SettingsPage::~SettingsPage()
{
delete ui;
}
SettingsPage::SettingsPage(QWidget *parent) :
QWidget(parent),
apm(AppManager::ins()),
ui(new Ui::SettingsPage)
{
ui->setupUi(this);
init();
}
void SettingsPage::init()
{
// load languages
QMapIterator<QString, QString> lang(apm->getLanguageList());
while (lang.hasNext()) {
lang.next();
ui->languagesCmb->addItem(lang.value(),lang.key());
}
QString lc = apm->getLanguageCode();
ui->languagesCmb->setCurrentText(apm->getLanguageList().value(lc));
// load themes
QMapIterator<QString, QString> theme(apm->getThemeList());
while (theme.hasNext()) {
theme.next();
ui->themesCmb->addItem(theme.value(),theme.key());
}
QString tn = apm->getThemeName();
ui->themesCmb->setCurrentText(apm->getThemeList().value(tn));
connect(ui->languagesCmb, SIGNAL(currentIndexChanged(int)), this, SLOT(languagesCmbChanged(int)));
connect(ui->themesCmb, SIGNAL(currentIndexChanged(int)), this, SLOT(themesCmbChanged(int)));
}
void SettingsPage::languagesCmbChanged(int index)
{
QString langCode = ui->languagesCmb->itemData(index).toString();
apm->setLanguage(langCode);
}
void SettingsPage::themesCmbChanged(int index)
{
QString themeName = ui->themesCmb->itemData(index).toString();
apm->setThemeName(themeName);
apm->updateStylesheet();
}

View File

@@ -0,0 +1,34 @@
#ifndef SETTINGS_PAGE_H
#define SETTINGS_PAGE_H
#include <QWidget>
#include <QMapIterator>
#include "Managers/app_manager.h"
namespace Ui {
class SettingsPage;
}
class SettingsPage : public QWidget
{
Q_OBJECT
public:
explicit SettingsPage(QWidget *parent = 0);
~SettingsPage();
private slots:
void init();
void themesCmbChanged(int index);
void languagesCmbChanged(int index);
private:
Ui::SettingsPage *ui;
private:
AppManager *apm;
};
#endif // SETTINGS_PAGE_H

View File

@@ -0,0 +1,105 @@
<?xml version="1.0" encoding="UTF-8"?>
<ui version="4.0">
<class>SettingsPage</class>
<widget class="QWidget" name="SettingsPage">
<property name="geometry">
<rect>
<x>0</x>
<y>0</y>
<width>733</width>
<height>479</height>
</rect>
</property>
<property name="sizePolicy">
<sizepolicy hsizetype="Expanding" vsizetype="Expanding">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="styleSheet">
<string notr="true"/>
</property>
<layout class="QGridLayout" name="gridLayout">
<property name="leftMargin">
<number>15</number>
</property>
<property name="topMargin">
<number>15</number>
</property>
<property name="rightMargin">
<number>15</number>
</property>
<property name="bottomMargin">
<number>15</number>
</property>
<property name="horizontalSpacing">
<number>30</number>
</property>
<property name="verticalSpacing">
<number>10</number>
</property>
<item row="1" column="0" alignment="Qt::AlignLeft">
<widget class="QComboBox" name="languagesCmb">
<property name="cursor">
<cursorShape>PointingHandCursor</cursorShape>
</property>
<property name="focusPolicy">
<enum>Qt::NoFocus</enum>
</property>
</widget>
</item>
<item row="0" column="0" alignment="Qt::AlignLeft">
<widget class="QLabel" name="langLabel">
<property name="text">
<string>Language</string>
</property>
</widget>
</item>
<item row="1" column="1" alignment="Qt::AlignLeft">
<widget class="QComboBox" name="themesCmb">
<property name="cursor">
<cursorShape>PointingHandCursor</cursorShape>
</property>
<property name="focusPolicy">
<enum>Qt::NoFocus</enum>
</property>
</widget>
</item>
<item row="0" column="1" alignment="Qt::AlignLeft">
<widget class="QLabel" name="themeLabel">
<property name="text">
<string>Theme</string>
</property>
</widget>
</item>
<item row="2" column="0" colspan="2">
<spacer name="verticalSpacer">
<property name="orientation">
<enum>Qt::Vertical</enum>
</property>
<property name="sizeHint" stdset="0">
<size>
<width>20</width>
<height>40</height>
</size>
</property>
</spacer>
</item>
<item row="0" column="2" rowspan="2">
<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>
<resources/>
<connections/>
</ui>

View File

@@ -0,0 +1,84 @@
#include "startup_app.h"
#include "ui_startup_app.h"
StartupApp::~StartupApp()
{
delete ui;
delete startupAppEdit;
}
StartupApp::StartupApp(QString appName, bool enabled, QString filePath, QWidget *parent) :
QWidget(parent),
ui(new Ui::StartupApp),
startupAppEdit(new StartupAppEdit),
appName(appName),
enabled(enabled),
filePath(filePath)
{
ui->setupUi(this);
ui->appName->setText(appName);
ui->startupCheck->setChecked(enabled);
ui->deleteAppBtn->setToolTip(tr("Delete"));
ui->editAppBtn->setToolTip(tr("Edit"));
connect(startupAppEdit, &StartupAppEdit::closeWindow, (StartupAppsPage*)parent, &StartupAppsPage::loadApps);
}
void StartupApp::on_startupCheck_clicked(bool status)
{
QStringList lines = FileUtil::readListFromFile(filePath);
int pos = lines.indexOf(QRegExp("X-GNOME-Autostart-enabled=.*"));
if(pos != -1)
{
lines.replace(pos, QString("X-GNOME-Autostart-enabled=%1").arg(status ? "true" : "false"));
FileUtil::writeFile(filePath, lines.join("\n"));
}
}
void StartupApp::on_deleteAppBtn_clicked()
{
if(QFile::remove(filePath))
deleteApp();
}
void StartupApp::on_editAppBtn_clicked()
{
StartupAppEdit::selectedFilePath = filePath;
startupAppEdit->show();
}
QString StartupApp::getAppName() const
{
return appName;
}
void StartupApp::setAppName(const QString &value)
{
appName = value;
}
bool StartupApp::getEnabled() const
{
return enabled;
}
void StartupApp::setEnabled(bool value)
{
enabled = value;
}
QString StartupApp::getFilePath() const
{
return filePath;
}
void StartupApp::setFilePath(const QString &value)
{
filePath = value;
}

View File

@@ -0,0 +1,51 @@
#ifndef STARTUP_APP_H
#define STARTUP_APP_H
#include <QWidget>
#include <QDebug>
#include <Utils/file_util.h>
#include "startup_app_edit.h"
#include "startup_apps_page.h"
namespace Ui {
class StartupApp;
}
class StartupApp : public QWidget
{
Q_OBJECT
public:
explicit StartupApp(QString appName, bool enabled, QString filePath, QWidget *parent = 0);
~StartupApp();
QString getAppName() const;
void setAppName(const QString &value);
bool getEnabled() const;
void setEnabled(bool value);
QString getFilePath() const;
void setFilePath(const QString &value);
private slots:
void on_startupCheck_clicked(bool);
void on_deleteAppBtn_clicked();
void on_editAppBtn_clicked();
signals:
void deleteApp();
private:
Ui::StartupApp *ui;
private:
QString appName;
QString appComment;
bool enabled;
QString filePath;
StartupAppEdit *startupAppEdit;
};
#endif // STARTUP_APP_H

View File

@@ -0,0 +1,177 @@
<?xml version="1.0" encoding="UTF-8"?>
<ui version="4.0">
<class>StartupApp</class>
<widget class="QWidget" name="StartupApp">
<property name="geometry">
<rect>
<x>0</x>
<y>0</y>
<width>661</width>
<height>45</height>
</rect>
</property>
<property name="sizePolicy">
<sizepolicy hsizetype="Expanding" vsizetype="Expanding">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="minimumSize">
<size>
<width>0</width>
<height>45</height>
</size>
</property>
<property name="windowTitle">
<string notr="true"/>
</property>
<layout class="QGridLayout" name="gridLayout">
<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>
<property name="spacing">
<number>0</number>
</property>
<item row="0" column="1">
<widget class="QWidget" name="startupAppWidget" native="true">
<property name="sizePolicy">
<sizepolicy hsizetype="Expanding" vsizetype="Expanding">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="cursor">
<cursorShape>ArrowCursor</cursorShape>
</property>
<layout class="QHBoxLayout" name="startupAppLayout">
<property name="spacing">
<number>15</number>
</property>
<property name="leftMargin">
<number>15</number>
</property>
<property name="topMargin">
<number>10</number>
</property>
<property name="rightMargin">
<number>10</number>
</property>
<property name="bottomMargin">
<number>10</number>
</property>
<item>
<widget class="QLabel" name="appIcon">
<property name="minimumSize">
<size>
<width>22</width>
<height>24</height>
</size>
</property>
<property name="maximumSize">
<size>
<width>22</width>
<height>24</height>
</size>
</property>
<property name="text">
<string/>
</property>
<property name="scaledContents">
<bool>true</bool>
</property>
</widget>
</item>
<item alignment="Qt::AlignLeft|Qt::AlignVCenter">
<widget class="QLabel" name="appName">
<property name="text">
<string notr="true">App Name</string>
</property>
</widget>
</item>
<item>
<spacer name="horizontalSpacer">
<property name="orientation">
<enum>Qt::Horizontal</enum>
</property>
<property name="sizeHint" stdset="0">
<size>
<width>0</width>
<height>0</height>
</size>
</property>
</spacer>
</item>
<item alignment="Qt::AlignRight|Qt::AlignVCenter">
<widget class="QPushButton" name="editAppBtn">
<property name="cursor">
<cursorShape>PointingHandCursor</cursorShape>
</property>
<property name="focusPolicy">
<enum>Qt::NoFocus</enum>
</property>
<property name="text">
<string/>
</property>
<property name="iconSize">
<size>
<width>18</width>
<height>20</height>
</size>
</property>
</widget>
</item>
<item alignment="Qt::AlignRight|Qt::AlignVCenter">
<widget class="QPushButton" name="deleteAppBtn">
<property name="cursor">
<cursorShape>PointingHandCursor</cursorShape>
</property>
<property name="focusPolicy">
<enum>Qt::NoFocus</enum>
</property>
<property name="text">
<string/>
</property>
<property name="iconSize">
<size>
<width>22</width>
<height>22</height>
</size>
</property>
</widget>
</item>
<item alignment="Qt::AlignRight|Qt::AlignVCenter">
<widget class="QCheckBox" name="startupCheck">
<property name="cursor">
<cursorShape>PointingHandCursor</cursorShape>
</property>
<property name="focusPolicy">
<enum>Qt::NoFocus</enum>
</property>
<property name="styleSheet">
<string notr="true"/>
</property>
<property name="iconSize">
<size>
<width>45</width>
<height>23</height>
</size>
</property>
</widget>
</item>
</layout>
</widget>
</item>
</layout>
</widget>
<resources/>
<connections/>
</ui>

View File

@@ -0,0 +1,117 @@
#include "startup_app_edit.h"
#include "ui_startup_app_edit.h"
StartupAppEdit::~StartupAppEdit()
{
delete ui;
}
QString StartupAppEdit::selectedFilePath = "";
StartupAppEdit::StartupAppEdit(QWidget *parent) :
QDialog(parent),
ui(new Ui::StartupAppEdit)
{
ui->setupUi(this);
init();
}
void StartupAppEdit::init()
{
setGeometry(
QStyle::alignedRect(
Qt::LeftToRight,
Qt::AlignCenter,
size(),
qApp->desktop()->availableGeometry())
);
ui->errorMsg->hide();
setStyleSheet(AppManager::ins()->getStylesheetFileContent());
newAppTemplate = "[Desktop Entry]\n"
"Name=%1\n"
"Comment=%2\n"
"Exec=%3\n"
"Type=Application\n"
"Terminal=false\n"
"X-GNOME-Autostart-enabled=true";
}
void StartupAppEdit::show()
{
// clear fields
ui->appNameTxt->clear();
ui->appCommentTxt->clear();
ui->appCommandTxt->clear();
ui->errorMsg->hide();
if(! selectedFilePath.isEmpty())
{
QStringList lines = FileUtil::readListFromFile(selectedFilePath);
if(! lines.isEmpty())
{
#define getValue(r) lines.filter(r).first().split("=").last().trimmed()
ui->appNameTxt->setText(getValue(NAME_REG));
ui->appCommentTxt->setText(getValue(COMMENT_REG));
ui->appCommandTxt->setText(getValue(EXEC_REG));
#undef getValue
}
}
QDialog::show();
}
void StartupAppEdit::on_saveBtn_clicked()
{
static QString autostartPath = QStandardPaths::writableLocation(QStandardPaths::ConfigLocation) + "/autostart";
if(isValid())
{
if(! selectedFilePath.isEmpty())
{
QStringList lines = FileUtil::readListFromFile(selectedFilePath);
lines.replace(lines.indexOf(NAME_REG), QString("Name=%1").arg(ui->appNameTxt->text()));
lines.replace(lines.indexOf(COMMENT_REG), QString("Comment=%1").arg(ui->appCommentTxt->text()));
lines.replace(lines.indexOf(EXEC_REG), QString("Exec=%1").arg(ui->appCommandTxt->text()));
FileUtil::writeFile(selectedFilePath, QString(lines.join("\n")), QIODevice::ReadWrite | QIODevice::Truncate);
}
else
{
// new file content
QString appContent = newAppTemplate
.arg(ui->appNameTxt->text())
.arg(ui->appCommentTxt->text())
.arg(ui->appCommandTxt->text());
// file name
QString appFileName = ui->appNameTxt->text()
.replace(" ", "_")
.replace(QRegExp("\\W+"), "");
QString path = QString("%1/%2.desktop").arg(autostartPath).arg(appFileName);
FileUtil::writeFile(path, appContent);
}
close();
closeWindow(); // signal
}
else {
ui->errorMsg->show();
}
selectedFilePath = "";
}
bool StartupAppEdit::isValid()
{
return ! ui->appNameTxt->text().isEmpty() &&
! ui->appCommentTxt->text().isEmpty() &&
! ui->appCommandTxt->text().isEmpty();
}

View File

@@ -0,0 +1,46 @@
#ifndef STARTUP_APP_EDIT_H
#define STARTUP_APP_EDIT_H
#include <QDialog>
#include <QDesktopWidget>
#include "Managers/app_manager.h"
#define NAME_REG QRegExp("(\\W+|^)Name=.*")
#define COMMENT_REG QRegExp("(\\W+|^)Comment=.*")
#define EXEC_REG QRegExp("(\\W+|^)Exec=.*")
namespace Ui {
class StartupAppEdit;
}
class StartupAppEdit : public QDialog
{
Q_OBJECT
public:
explicit StartupAppEdit(QWidget *parent = 0);
~StartupAppEdit();
public:
static QString selectedFilePath;
signals:
void closeWindow();
public slots:
void show();
private slots:
void init();
bool isValid();
void on_saveBtn_clicked();
private:
Ui::StartupAppEdit *ui;
private:
QString newAppTemplate;
};
#endif // STARTUP_APP_EDIT_H

View File

@@ -0,0 +1,115 @@
<?xml version="1.0" encoding="UTF-8"?>
<ui version="4.0">
<class>StartupAppEdit</class>
<widget class="QDialog" name="StartupAppEdit">
<property name="geometry">
<rect>
<x>0</x>
<y>0</y>
<width>380</width>
<height>260</height>
</rect>
</property>
<property name="minimumSize">
<size>
<width>380</width>
<height>260</height>
</size>
</property>
<property name="windowTitle">
<string>Startup App</string>
</property>
<property name="modal">
<bool>true</bool>
</property>
<layout class="QGridLayout" name="gridLayout">
<property name="leftMargin">
<number>30</number>
</property>
<property name="topMargin">
<number>20</number>
</property>
<property name="rightMargin">
<number>30</number>
</property>
<property name="bottomMargin">
<number>20</number>
</property>
<property name="spacing">
<number>15</number>
</property>
<item row="6" column="1" alignment="Qt::AlignRight|Qt::AlignVCenter">
<widget class="QPushButton" name="saveBtn">
<property name="cursor">
<cursorShape>PointingHandCursor</cursorShape>
</property>
<property name="focusPolicy">
<enum>Qt::NoFocus</enum>
</property>
<property name="text">
<string>Save</string>
</property>
<property name="default">
<bool>true</bool>
</property>
</widget>
</item>
<item row="6" column="0">
<widget class="QLabel" name="errorMsg">
<property name="text">
<string>Fields cannot be left blank. </string>
</property>
</widget>
</item>
<item row="4" column="0" colspan="2">
<widget class="QLineEdit" name="appCommentTxt">
<property name="placeholderText">
<string>App Comment</string>
</property>
</widget>
</item>
<item row="1" column="0" colspan="2">
<widget class="QLineEdit" name="appNameTxt">
<property name="placeholderText">
<string>App Name</string>
</property>
</widget>
</item>
<item row="5" column="0" colspan="2">
<widget class="QLineEdit" name="appCommandTxt">
<property name="placeholderText">
<string>Command</string>
</property>
</widget>
</item>
<item row="0" column="0" colspan="2" alignment="Qt::AlignHCenter">
<widget class="QLabel" name="title">
<property name="text">
<string>Application</string>
</property>
</widget>
</item>
<item row="8" column="0" colspan="2">
<spacer name="verticalSpacer">
<property name="orientation">
<enum>Qt::Vertical</enum>
</property>
<property name="sizeHint" stdset="0">
<size>
<width>20</width>
<height>0</height>
</size>
</property>
</spacer>
</item>
</layout>
</widget>
<tabstops>
<tabstop>appNameTxt</tabstop>
<tabstop>appCommentTxt</tabstop>
<tabstop>appCommandTxt</tabstop>
<tabstop>saveBtn</tabstop>
</tabstops>
<resources/>
<connections/>
</ui>

View File

@@ -0,0 +1,90 @@
#include "startup_apps_page.h"
#include "ui_startup_apps_page.h"
StartupAppsPage::~StartupAppsPage()
{
delete ui;
delete startupAppEdit;
}
StartupAppsPage::StartupAppsPage(QWidget *parent) :
QWidget(parent),
ui(new Ui::StartupAppsPage),
startupAppEdit(new StartupAppEdit)
{
ui->setupUi(this);
init();
}
void StartupAppsPage::init()
{
loadApps();
connect(startupAppEdit, &StartupAppEdit::closeWindow, this, &StartupAppsPage::loadApps);
}
void StartupAppsPage::loadApps()
{
// clear layout
ui->startupListWidget->clear();
static QString autostartPath = QStandardPaths::writableLocation(QStandardPaths::ConfigLocation) + "/autostart";
QDir autostartFiles(autostartPath, "*.desktop");
foreach (QFileInfo f, autostartFiles.entryInfoList())
{
QStringList lines = FileUtil::readListFromFile(f.absoluteFilePath());
QStringList d_name = lines.filter(QRegExp("(\\W+|^)Name=")); // get name
if(! d_name.isEmpty()) // has a name
{
QString appName = d_name.first().split("=").last().trimmed();
QStringList d_autostart = lines.filter(QRegExp("(\\W+|^)X-GNOME-Autostart-enabled="));
bool enabled = false;
if(! d_autostart.isEmpty())
{
// X-GNOME-Autostart-enabled=[true|false]
QString status = d_autostart.first()
.split("=").last().toLower().trimmed();
enabled = ! status.compare("true");
}
QListWidgetItem *item = new QListWidgetItem(ui->startupListWidget);
// new app
StartupApp *app = new StartupApp(appName, enabled, f.absoluteFilePath(), this);
// delete button click
connect(app, &StartupApp::deleteApp, this, &StartupAppsPage::loadApps);
item->setSizeHint(app->sizeHint());
ui->startupListWidget->setItemWidget(item, app);
}
}
setAppCount();
}
void StartupAppsPage::setAppCount()
{
int count = ui->startupListWidget->count();
ui->startupAppsTitleLbl->setText(
tr("System Startup Applications (%1)")
.arg(QString::number(count)));
ui->notFoundWidget->setVisible(! count);
ui->startupListWidget->setVisible(count);
}
void StartupAppsPage::on_addStartupAppBtn_clicked()
{
StartupAppEdit::selectedFilePath = "";
startupAppEdit->show();
}

View File

@@ -0,0 +1,39 @@
#ifndef STARTUPAPPSPAGE_H
#define STARTUPAPPSPAGE_H
#include <QWidget>
#include <QDebug>
#include "startup_app.h"
#include "startup_app_edit.h"
#include <Utils/file_util.h>
namespace Ui {
class StartupAppsPage;
}
class StartupAppsPage : public QWidget
{
Q_OBJECT
public:
explicit StartupAppsPage(QWidget *parent = 0);
~StartupAppsPage();
public slots:
void loadApps();
private slots:
void init();
void on_addStartupAppBtn_clicked();
void setAppCount();
private:
Ui::StartupAppsPage *ui;
private:
StartupAppEdit *startupAppEdit;
};
#endif // STARTUPAPPSPAGE_H

View File

@@ -0,0 +1,243 @@
<?xml version="1.0" encoding="UTF-8"?>
<ui version="4.0">
<class>StartupAppsPage</class>
<widget class="QWidget" name="StartupAppsPage">
<property name="geometry">
<rect>
<x>0</x>
<y>0</y>
<width>892</width>
<height>591</height>
</rect>
</property>
<property name="windowTitle">
<string notr="true"/>
</property>
<layout class="QGridLayout" name="gridLayout">
<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 row="0" column="0">
<widget class="QWidget" name="verticalWidget" native="true">
<property name="sizePolicy">
<sizepolicy hsizetype="Preferred" vsizetype="Expanding">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="cursor">
<cursorShape>ArrowCursor</cursorShape>
</property>
<property name="styleSheet">
<string notr="true"/>
</property>
<layout class="QGridLayout" name="gridLayout_2">
<property name="leftMargin">
<number>60</number>
</property>
<property name="topMargin">
<number>20</number>
</property>
<property name="rightMargin">
<number>60</number>
</property>
<property name="bottomMargin">
<number>30</number>
</property>
<property name="spacing">
<number>5</number>
</property>
<item row="0" column="1">
<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>
<item row="5" column="2">
<widget class="QPushButton" name="addStartupAppBtn">
<property name="sizePolicy">
<sizepolicy hsizetype="Fixed" vsizetype="Fixed">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="font">
<font>
<family>Ubuntu</family>
</font>
</property>
<property name="cursor">
<cursorShape>PointingHandCursor</cursorShape>
</property>
<property name="focusPolicy">
<enum>Qt::NoFocus</enum>
</property>
<property name="styleSheet">
<string notr="true"/>
</property>
<property name="text">
<string>Add Startup App</string>
</property>
</widget>
</item>
<item row="0" column="0" alignment="Qt::AlignLeft">
<widget class="QLabel" name="startupAppsTitleLbl">
<property name="font">
<font>
<family>Ubuntu</family>
<pointsize>11</pointsize>
<italic>false</italic>
</font>
</property>
<property name="styleSheet">
<string notr="true"/>
</property>
<property name="text">
<string>System Startup Applications</string>
</property>
</widget>
</item>
<item row="4" column="0" colspan="3">
<spacer name="verticalSpacer_2">
<property name="orientation">
<enum>Qt::Vertical</enum>
</property>
<property name="sizeType">
<enum>QSizePolicy::Fixed</enum>
</property>
<property name="sizeHint" stdset="0">
<size>
<width>20</width>
<height>20</height>
</size>
</property>
</spacer>
</item>
<item row="1" column="0" colspan="3">
<widget class="QWidget" name="verticalWidget" native="true">
<layout class="QVBoxLayout" name="verticalLayout">
<property name="spacing">
<number>0</number>
</property>
<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="QWidget" name="notFoundWidget" native="true">
<property name="sizePolicy">
<sizepolicy hsizetype="Preferred" vsizetype="Expanding">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="minimumSize">
<size>
<width>0</width>
<height>200</height>
</size>
</property>
<property name="maximumSize">
<size>
<width>16777215</width>
<height>200</height>
</size>
</property>
<property name="styleSheet">
<string notr="true"/>
</property>
<layout class="QVBoxLayout" name="notFoundLayout">
<property name="spacing">
<number>0</number>
</property>
<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 alignment="Qt::AlignHCenter|Qt::AlignBottom">
<widget class="QLabel" name="label">
<property name="text">
<string>Not Found Startup Apps</string>
</property>
</widget>
</item>
</layout>
</widget>
</item>
<item>
<widget class="QListWidget" name="startupListWidget">
<property name="focusPolicy">
<enum>Qt::NoFocus</enum>
</property>
<property name="frameShape">
<enum>QFrame::NoFrame</enum>
</property>
<property name="horizontalScrollBarPolicy">
<enum>Qt::ScrollBarAlwaysOff</enum>
</property>
<property name="editTriggers">
<set>QAbstractItemView::EditKeyPressed</set>
</property>
<property name="selectionMode">
<enum>QAbstractItemView::NoSelection</enum>
</property>
<property name="selectionBehavior">
<enum>QAbstractItemView::SelectRows</enum>
</property>
<property name="resizeMode">
<enum>QListView::Adjust</enum>
</property>
<property name="layoutMode">
<enum>QListView::Batched</enum>
</property>
<property name="spacing">
<number>5</number>
</property>
<property name="uniformItemSizes">
<bool>true</bool>
</property>
</widget>
</item>
</layout>
</widget>
</item>
</layout>
</widget>
</item>
</layout>
</widget>
<resources/>
<connections/>
</ui>

View File

@@ -0,0 +1,315 @@
#include "system_cleaner_page.h"
#include "ui_system_cleaner_page.h"
SystemCleanerPage::~SystemCleanerPage()
{
delete ui;
delete loadingMovie;
delete loadingMovie_2;
}
SystemCleanerPage::SystemCleanerPage(QWidget *parent) :
QWidget(parent),
im(InfoManager::ins()),
tmr(ToolManager::ins()),
defaultIcon(QIcon::fromTheme("application-x-executable")),
ui(new Ui::SystemCleanerPage)
{
ui->setupUi(this);
init();
ui->stackedWidget->setCurrentIndex(0);
}
void SystemCleanerPage::init()
{
// treview settings
ui->scanResultTreeW->setColumnCount(2);
ui->scanResultTreeW->setColumnWidth(0, 600);
ui->scanResultTreeW->header()->setFixedHeight(30);
ui->scanResultTreeW->setHeaderLabels({ tr("File Name"), tr("Size") });
// loaders
connect(AppManager::ins(), &AppManager::changedTheme, this, [this]() {
loadingMovie = new QMovie(QString(":/static/themes/%1/img/scanLoading.gif").arg(AppManager::ins()->getThemeName()));
ui->loading->setMovie(loadingMovie);
loadingMovie->start();
ui->loading->hide();
loadingMovie_2 = new QMovie(QString(":/static/themes/%1/img/loading.gif").arg(AppManager::ins()->getThemeName()));
ui->loading_2->setMovie(loadingMovie_2);
loadingMovie_2->start();
ui->loading_2->hide();
});
}
void SystemCleanerPage::addTreeRoot(CleanCategories cat, QString title, QFileInfoList infos, bool noChild)
{
QTreeWidgetItem *root = new QTreeWidgetItem(ui->scanResultTreeW);
root->setData(2, 0, cat);
root->setData(2, 1, title);
if (! infos.isEmpty())
root->setData(3, 0, infos.at(0).absoluteDir().path());
root->setCheckState(0, Qt::Unchecked);
// add children
quint64 totalSize = 0;
if(! noChild) {
foreach (QFileInfo i, infos) {
quint64 size = FileUtil::getFileSize(i.absoluteFilePath());
addTreeChild(i.absoluteFilePath(), i.fileName(), size, root);
totalSize += size;
}
root->setText(0, QString("%1 (%2)")
.arg(title)
.arg(infos.count()));
} else {
if (! infos.isEmpty())
totalSize += FileUtil::getFileSize(infos.first().absoluteFilePath());
root->setText(0, QString("%1")
.arg(title));
}
root->setText(1, QString("%1").arg(FormatUtil::formatBytes(totalSize)));
}
void SystemCleanerPage::addTreeChild(QString data, QString text, quint64 size, QTreeWidgetItem *parent)
{
QTreeWidgetItem *item = new QTreeWidgetItem(parent);
item->setIcon(0, QIcon::fromTheme(text, defaultIcon));
item->setText(0, text);
item->setText(1, FormatUtil::formatBytes(size));
item->setData(2, 0, data);
item->setCheckState(0, Qt::Unchecked);
}
void SystemCleanerPage::addTreeChild(CleanCategories cat, QString text, quint64 size)
{
QTreeWidgetItem *item = new QTreeWidgetItem(ui->scanResultTreeW);
item->setText(0, text);
item->setText(1, FormatUtil::formatBytes(size));
item->setData(2, 0, cat);
item->setCheckState(0, Qt::Unchecked);
}
void SystemCleanerPage::on_scanResultTreeW_itemClicked(QTreeWidgetItem *item, int column)
{
if(column == 0) {
// new check state
Qt::CheckState cs = (item->checkState(column) == Qt::Checked ? Qt::Unchecked : Qt::Checked);
// update check state
item->setCheckState(column, cs);
// change check state if has children
for (int i = 0; i < item->childCount(); ++i)
item->child(i)->setCheckState(column, cs);
}
}
void SystemCleanerPage::systemScan()
{
if (ui->packageCacheCheck->isChecked() ||
ui->crashReportsCheck->isChecked() ||
ui->logCheck->isChecked() ||
ui->appCacheCheck->isChecked() ||
ui->trashCheck->isChecked()
){
ui->scanBtn->hide();
ui->loading->show();
ui->packageCacheCheck->setEnabled(false);
ui->crashReportsCheck->setEnabled(false);
ui->logCheck->setEnabled(false);
ui->appCacheCheck->setEnabled(false);
ui->trashCheck->setEnabled(false);
QThread::sleep(1);
ui->scanResultTreeW->clear();
// Package Caches
if (ui->packageCacheCheck->isChecked()) {
addTreeRoot(PACKAGE_CACHE,
ui->packageCacheLabel->text(),
tmr->getPackageCaches());
}
// Crash Reports
if (ui->crashReportsCheck->isChecked()) {
addTreeRoot(CRASH_REPORTS,
ui->crashReportsLabel->text(),
im->getCrashReports());
}
// Application Logs
if (ui->logCheck->isChecked()) {
addTreeRoot(APPLICATION_LOGS,
ui->logLabel->text(),
im->getAppLogs());
}
// Application Cache
if (ui->appCacheCheck->isChecked()) {
addTreeRoot(APPLICATION_CACHES,
ui->appCacheLabel->text(),
im->getAppCaches());
}
// Trash
if(ui->trashCheck->isChecked()) {
addTreeRoot(TRASH,
ui->trashLabel->text(),
{ QFileInfo("/home/oguzhan/.local/share/Trash/") },
true);
}
// scan results page
ui->stackedWidget->setCurrentIndex(1);
ui->packageCacheCheck->setChecked(false);
ui->crashReportsCheck->setChecked(false);
ui->logCheck->setChecked(false);
ui->appCacheCheck->setChecked(false);
ui->trashCheck->setChecked(false);
}
}
bool SystemCleanerPage::cleanValid()
{
for (int i = 0; i < ui->scanResultTreeW->topLevelItemCount(); ++i) {
QTreeWidgetItem *it = ui->scanResultTreeW->topLevelItem(i);
if (it->checkState(0) == Qt::Checked)
return true;
for (int j = 0; j < it->childCount(); ++j)
if (it->child(j)->checkState(0) == Qt::Checked)
return true;
}
return false;
}
void SystemCleanerPage::systemClean()
{
if (cleanValid())
{
ui->cleanBtn->hide();
ui->loading_2->show();
ui->scanResultTreeW->setEnabled(false);
quint64 totalCleanedSize = 0;
QTreeWidget *tree = ui->scanResultTreeW;
QStringList filesToDelete;
QList<QTreeWidgetItem *> children;
for (int i = 0; i < tree->topLevelItemCount(); ++i) {
QTreeWidgetItem *it = tree->topLevelItem(i);
CleanCategories cat = (CleanCategories) it->data(2, 0).toInt();
// Package Caches | Crash Reports | Application Logs | Application Caches
if (cat != CleanCategories::TRASH) {
for (int j = 0; j < it->childCount(); ++j) { // files
if(it->child(j)->checkState(0) == Qt::Checked) { // if checked
QString filePath = it->child(j)->data(2, 0).toString();
filesToDelete << filePath;
children.append(it->child(j));
}
}
}
// Trash
else if (cat == CleanCategories::TRASH) {
if (it->checkState(0) == Qt::Checked) {
QString homePath = QStandardPaths::writableLocation(QStandardPaths::HomeLocation);
QDir(homePath + "/.local/share/Trash/files").removeRecursively();
QDir(homePath + "/.local/share/Trash/info").removeRecursively();
}
}
}
// get removed files total size
foreach (QString file, filesToDelete) {
totalCleanedSize += FileUtil::getFileSize(file);
}
// remove selected files
if(! filesToDelete.isEmpty()) {
CommandUtil::sudoExec("rm", QStringList() << "-rf" << filesToDelete);
}
QThread::sleep(1);
for (int i = 0; i < tree->topLevelItemCount(); ++i) {
// clear removed childs
foreach (QTreeWidgetItem *item, children) {
tree->topLevelItem(i)->removeChild(item);
}
}
// update titles
for (int i = 0; i < tree->topLevelItemCount(); ++i) {
QTreeWidgetItem *it = tree->topLevelItem(i);
it->setText(0, QString("%1 (%2)")
.arg(it->data(2, 1).toString())
.arg(it->childCount()));
it->setText(1, QString("%1")
.arg(FormatUtil::formatBytes(FileUtil::getFileSize(it->data(3, 0).toString()))));
}
ui->removedTotalSizeLbl->setText(tr("%1 size files cleaned.")
.arg(FormatUtil::formatBytes(totalCleanedSize)));
ui->cleanBtn->show();
ui->loading_2->hide();
ui->scanResultTreeW->setEnabled(true);
}
}
void SystemCleanerPage::on_scanBtn_clicked()
{
QtConcurrent::run(this, &SystemCleanerPage::systemScan);
}
void SystemCleanerPage::on_cleanBtn_clicked()
{
QtConcurrent::run(this, &SystemCleanerPage::systemClean);
}
void SystemCleanerPage::on_backButtton_clicked()
{
ui->scanBtn->show();
ui->loading->hide();
ui->packageCacheCheck->setEnabled(true);
ui->crashReportsCheck->setEnabled(true);
ui->logCheck->setEnabled(true);
ui->appCacheCheck->setEnabled(true);
ui->trashCheck->setEnabled(true);
ui->scanResultTreeW->clear();
ui->stackedWidget->setCurrentIndex(0);
}

View File

@@ -0,0 +1,64 @@
#ifndef SYSTEMCLEANERPAGE_H
#define SYSTEMCLEANERPAGE_H
#include <QWidget>
#include <QTreeWidgetItem>
#include <QMap>
#include <QMovie>
#include <QDebug>
#include <QtConcurrent>
#include <QThread>
#include "Managers/app_manager.h"
#include <Managers/info_manager.h>
#include <Managers/tool_manager.h>
namespace Ui {
class SystemCleanerPage;
}
class SystemCleanerPage : public QWidget
{
Q_OBJECT
public:
enum CleanCategories {
PACKAGE_CACHE,
CRASH_REPORTS,
APPLICATION_LOGS,
APPLICATION_CACHES,
TRASH
};
public:
explicit SystemCleanerPage(QWidget *parent = 0);
~SystemCleanerPage();
private slots:
void init();
void addTreeRoot(CleanCategories cat, QString title, QFileInfoList infos, bool noChild = false);
void addTreeChild(CleanCategories cat, QString text, quint64 size);
void addTreeChild(QString data, QString text, quint64 size, QTreeWidgetItem *parent);
void on_scanResultTreeW_itemClicked(QTreeWidgetItem *item, int column);
void on_cleanBtn_clicked();
void on_scanBtn_clicked();
void on_backButtton_clicked();
void systemScan();
void systemClean();
bool cleanValid();
private:
Ui::SystemCleanerPage *ui;
private:
InfoManager *im;
ToolManager *tmr;
QIcon defaultIcon;
QMovie *loadingMovie;
QMovie *loadingMovie_2;
};
#endif // SYSTEMCLEANERPAGE_H

View File

@@ -0,0 +1,636 @@
<?xml version="1.0" encoding="UTF-8"?>
<ui version="4.0">
<class>SystemCleanerPage</class>
<widget class="QWidget" name="SystemCleanerPage">
<property name="geometry">
<rect>
<x>0</x>
<y>0</y>
<width>784</width>
<height>507</height>
</rect>
</property>
<property name="windowTitle">
<string notr="true"/>
</property>
<layout class="QVBoxLayout" name="verticalLayout">
<property name="spacing">
<number>0</number>
</property>
<property name="leftMargin">
<number>15</number>
</property>
<property name="topMargin">
<number>0</number>
</property>
<property name="rightMargin">
<number>15</number>
</property>
<property name="bottomMargin">
<number>15</number>
</property>
<item>
<widget class="QStackedWidget" name="stackedWidget">
<property name="styleSheet">
<string notr="true"/>
</property>
<property name="currentIndex">
<number>1</number>
</property>
<widget class="QWidget" name="cleanerCategories">
<layout class="QGridLayout" name="gridLayout_3">
<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>
<property name="horizontalSpacing">
<number>40</number>
</property>
<property name="verticalSpacing">
<number>20</number>
</property>
<item row="2" column="3" alignment="Qt::AlignHCenter">
<widget class="QLabel" name="crashReportsLabel">
<property name="text">
<string>Crash Reports</string>
</property>
<property name="alignment">
<set>Qt::AlignCenter</set>
</property>
<property name="wordWrap">
<bool>true</bool>
</property>
</widget>
</item>
<item row="1" column="3" alignment="Qt::AlignHCenter|Qt::AlignTop">
<widget class="QLabel" name="crashReportsImgLabel">
<property name="minimumSize">
<size>
<width>90</width>
<height>90</height>
</size>
</property>
<property name="maximumSize">
<size>
<width>90</width>
<height>90</height>
</size>
</property>
<property name="text">
<string/>
</property>
<property name="pixmap">
<pixmap resource="../../static.qrc">:/static/themes/default/img/c_crash.png</pixmap>
</property>
<property name="scaledContents">
<bool>false</bool>
</property>
<property name="alignment">
<set>Qt::AlignCenter</set>
</property>
</widget>
</item>
<item row="3" column="5" alignment="Qt::AlignHCenter">
<widget class="QCheckBox" name="appCacheCheck">
<property name="cursor">
<cursorShape>PointingHandCursor</cursorShape>
</property>
<property name="focusPolicy">
<enum>Qt::NoFocus</enum>
</property>
<property name="text">
<string/>
</property>
</widget>
</item>
<item row="7" column="2" colspan="5">
<spacer name="verticalSpacer_4">
<property name="orientation">
<enum>Qt::Vertical</enum>
</property>
<property name="sizeHint" stdset="0">
<size>
<width>20</width>
<height>0</height>
</size>
</property>
</spacer>
</item>
<item row="1" column="1">
<spacer name="horizontalSpacer_2">
<property name="orientation">
<enum>Qt::Horizontal</enum>
</property>
<property name="sizeHint" stdset="0">
<size>
<width>40</width>
<height>20</height>
</size>
</property>
</spacer>
</item>
<item row="1" column="5" alignment="Qt::AlignHCenter">
<widget class="QLabel" name="appCacheImgLabel">
<property name="minimumSize">
<size>
<width>90</width>
<height>90</height>
</size>
</property>
<property name="maximumSize">
<size>
<width>90</width>
<height>90</height>
</size>
</property>
<property name="text">
<string/>
</property>
<property name="pixmap">
<pixmap resource="../../static.qrc">:/static/themes/default/img/c_cache.png</pixmap>
</property>
<property name="alignment">
<set>Qt::AlignCenter</set>
</property>
</widget>
</item>
<item row="2" column="4" alignment="Qt::AlignHCenter">
<widget class="QLabel" name="logLabel">
<property name="text">
<string>Application Logs</string>
</property>
<property name="alignment">
<set>Qt::AlignCenter</set>
</property>
<property name="wordWrap">
<bool>true</bool>
</property>
</widget>
</item>
<item row="1" column="6" alignment="Qt::AlignHCenter">
<widget class="QLabel" name="trashImgLabel">
<property name="minimumSize">
<size>
<width>90</width>
<height>90</height>
</size>
</property>
<property name="maximumSize">
<size>
<width>90</width>
<height>90</height>
</size>
</property>
<property name="text">
<string/>
</property>
<property name="pixmap">
<pixmap resource="../../static.qrc">:/static/themes/default/img/c_trash.png</pixmap>
</property>
<property name="alignment">
<set>Qt::AlignCenter</set>
</property>
</widget>
</item>
<item row="2" column="5" alignment="Qt::AlignHCenter">
<widget class="QLabel" name="appCacheLabel">
<property name="text">
<string>Application Caches</string>
</property>
<property name="alignment">
<set>Qt::AlignCenter</set>
</property>
<property name="wordWrap">
<bool>true</bool>
</property>
</widget>
</item>
<item row="1" column="2" alignment="Qt::AlignHCenter">
<widget class="QLabel" name="packageCacheImgLabel">
<property name="minimumSize">
<size>
<width>90</width>
<height>90</height>
</size>
</property>
<property name="maximumSize">
<size>
<width>90</width>
<height>90</height>
</size>
</property>
<property name="textFormat">
<enum>Qt::AutoText</enum>
</property>
<property name="pixmap">
<pixmap resource="../../static.qrc">:/static/themes/default/img/c_package.png</pixmap>
</property>
<property name="scaledContents">
<bool>false</bool>
</property>
<property name="alignment">
<set>Qt::AlignCenter</set>
</property>
</widget>
</item>
<item row="3" column="6" alignment="Qt::AlignHCenter">
<widget class="QCheckBox" name="trashCheck">
<property name="cursor">
<cursorShape>PointingHandCursor</cursorShape>
</property>
<property name="focusPolicy">
<enum>Qt::NoFocus</enum>
</property>
<property name="text">
<string/>
</property>
</widget>
</item>
<item row="3" column="3" alignment="Qt::AlignHCenter">
<widget class="QCheckBox" name="crashReportsCheck">
<property name="cursor">
<cursorShape>PointingHandCursor</cursorShape>
</property>
<property name="focusPolicy">
<enum>Qt::NoFocus</enum>
</property>
<property name="text">
<string/>
</property>
</widget>
</item>
<item row="5" column="4" alignment="Qt::AlignHCenter">
<widget class="QPushButton" name="scanBtn">
<property name="minimumSize">
<size>
<width>100</width>
<height>100</height>
</size>
</property>
<property name="cursor">
<cursorShape>PointingHandCursor</cursorShape>
</property>
<property name="focusPolicy">
<enum>Qt::NoFocus</enum>
</property>
<property name="text">
<string/>
</property>
<property name="iconSize">
<size>
<width>100</width>
<height>100</height>
</size>
</property>
</widget>
</item>
<item row="4" column="4">
<spacer name="verticalSpacer_5">
<property name="orientation">
<enum>Qt::Vertical</enum>
</property>
<property name="sizeType">
<enum>QSizePolicy::Fixed</enum>
</property>
<property name="sizeHint" stdset="0">
<size>
<width>20</width>
<height>30</height>
</size>
</property>
</spacer>
</item>
<item row="3" column="2" alignment="Qt::AlignHCenter|Qt::AlignTop">
<widget class="QCheckBox" name="packageCacheCheck">
<property name="cursor">
<cursorShape>PointingHandCursor</cursorShape>
</property>
<property name="focusPolicy">
<enum>Qt::NoFocus</enum>
</property>
<property name="text">
<string/>
</property>
</widget>
</item>
<item row="2" column="6" alignment="Qt::AlignHCenter">
<widget class="QLabel" name="trashLabel">
<property name="text">
<string>Trash</string>
</property>
<property name="alignment">
<set>Qt::AlignCenter</set>
</property>
<property name="wordWrap">
<bool>true</bool>
</property>
</widget>
</item>
<item row="1" column="4" alignment="Qt::AlignHCenter|Qt::AlignTop">
<widget class="QLabel" name="logImageLabel">
<property name="minimumSize">
<size>
<width>90</width>
<height>90</height>
</size>
</property>
<property name="maximumSize">
<size>
<width>90</width>
<height>90</height>
</size>
</property>
<property name="text">
<string/>
</property>
<property name="pixmap">
<pixmap resource="../../static.qrc">:/static/themes/default/img/c_logs.png</pixmap>
</property>
<property name="alignment">
<set>Qt::AlignCenter</set>
</property>
</widget>
</item>
<item row="2" column="2" alignment="Qt::AlignHCenter">
<widget class="QLabel" name="packageCacheLabel">
<property name="text">
<string>Package Caches</string>
</property>
<property name="alignment">
<set>Qt::AlignCenter</set>
</property>
<property name="wordWrap">
<bool>true</bool>
</property>
</widget>
</item>
<item row="3" column="4" alignment="Qt::AlignHCenter">
<widget class="QCheckBox" name="logCheck">
<property name="cursor">
<cursorShape>PointingHandCursor</cursorShape>
</property>
<property name="focusPolicy">
<enum>Qt::NoFocus</enum>
</property>
<property name="text">
<string/>
</property>
</widget>
</item>
<item row="1" column="8">
<spacer name="horizontalSpacer_3">
<property name="orientation">
<enum>Qt::Horizontal</enum>
</property>
<property name="sizeHint" stdset="0">
<size>
<width>40</width>
<height>20</height>
</size>
</property>
</spacer>
</item>
<item row="0" column="4">
<spacer name="verticalSpacer">
<property name="orientation">
<enum>Qt::Vertical</enum>
</property>
<property name="sizeHint" stdset="0">
<size>
<width>20</width>
<height>100</height>
</size>
</property>
</spacer>
</item>
<item row="6" column="4" alignment="Qt::AlignHCenter">
<widget class="QLabel" name="loading">
<property name="minimumSize">
<size>
<width>100</width>
<height>100</height>
</size>
</property>
<property name="text">
<string/>
</property>
</widget>
</item>
</layout>
</widget>
<widget class="QWidget" name="cleanerPage">
<layout class="QVBoxLayout" name="verticalLayout_2">
<property name="spacing">
<number>0</number>
</property>
<property name="leftMargin">
<number>0</number>
</property>
<property name="topMargin">
<number>5</number>
</property>
<property name="rightMargin">
<number>0</number>
</property>
<property name="bottomMargin">
<number>0</number>
</property>
<item>
<widget class="QWidget" name="gridWidget" native="true">
<layout class="QGridLayout" name="gridLayout">
<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>
<property name="horizontalSpacing">
<number>0</number>
</property>
<property name="verticalSpacing">
<number>10</number>
</property>
<item row="0" column="0" alignment="Qt::AlignLeft">
<widget class="QPushButton" name="backButtton">
<property name="cursor">
<cursorShape>PointingHandCursor</cursorShape>
</property>
<property name="text">
<string> Back</string>
</property>
<property name="icon">
<iconset resource="../../static.qrc">
<normaloff>:/static/themes/default/img/back.svg</normaloff>:/static/themes/default/img/back.svg</iconset>
</property>
<property name="iconSize">
<size>
<width>20</width>
<height>20</height>
</size>
</property>
</widget>
</item>
<item row="3" column="3">
<spacer name="horizontalSpacer_5">
<property name="orientation">
<enum>Qt::Horizontal</enum>
</property>
<property name="sizeHint" stdset="0">
<size>
<width>40</width>
<height>20</height>
</size>
</property>
</spacer>
</item>
<item row="3" column="0">
<spacer name="horizontalSpacer_4">
<property name="orientation">
<enum>Qt::Horizontal</enum>
</property>
<property name="sizeHint" stdset="0">
<size>
<width>40</width>
<height>20</height>
</size>
</property>
</spacer>
</item>
<item row="1" column="0" rowspan="2" colspan="4">
<widget class="QTreeWidget" name="scanResultTreeW">
<property name="font">
<font>
<stylestrategy>PreferAntialias</stylestrategy>
</font>
</property>
<property name="cursor" stdset="0">
<cursorShape>ArrowCursor</cursorShape>
</property>
<property name="focusPolicy">
<enum>Qt::NoFocus</enum>
</property>
<property name="styleSheet">
<string notr="true"/>
</property>
<property name="editTriggers">
<set>QAbstractItemView::NoEditTriggers</set>
</property>
<property name="selectionMode">
<enum>QAbstractItemView::NoSelection</enum>
</property>
<property name="textElideMode">
<enum>Qt::ElideMiddle</enum>
</property>
<property name="horizontalScrollMode">
<enum>QAbstractItemView::ScrollPerItem</enum>
</property>
<property name="animated">
<bool>true</bool>
</property>
<attribute name="headerVisible">
<bool>true</bool>
</attribute>
<column>
<property name="text">
<string notr="true">1</string>
</property>
</column>
</widget>
</item>
<item row="3" column="1" alignment="Qt::AlignHCenter">
<widget class="QPushButton" name="cleanBtn">
<property name="sizePolicy">
<sizepolicy hsizetype="Fixed" vsizetype="Fixed">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="minimumSize">
<size>
<width>100</width>
<height>100</height>
</size>
</property>
<property name="maximumSize">
<size>
<width>100</width>
<height>100</height>
</size>
</property>
<property name="cursor">
<cursorShape>PointingHandCursor</cursorShape>
</property>
<property name="focusPolicy">
<enum>Qt::NoFocus</enum>
</property>
<property name="styleSheet">
<string notr="true"/>
</property>
<property name="text">
<string/>
</property>
</widget>
</item>
<item row="0" column="1" alignment="Qt::AlignHCenter">
<widget class="QLabel" name="removedTotalSizeLbl">
<property name="minimumSize">
<size>
<width>20</width>
<height>0</height>
</size>
</property>
<property name="styleSheet">
<string notr="true"/>
</property>
<property name="text">
<string/>
</property>
</widget>
</item>
<item row="4" column="1">
<widget class="QLabel" name="loading_2">
<property name="minimumSize">
<size>
<width>100</width>
<height>20</height>
</size>
</property>
<property name="maximumSize">
<size>
<width>16777215</width>
<height>20</height>
</size>
</property>
<property name="text">
<string/>
</property>
</widget>
</item>
</layout>
</widget>
</item>
</layout>
</widget>
</widget>
</item>
</layout>
</widget>
<resources>
<include location="../../static.qrc"/>
</resources>
<connections/>
</ui>

View File

@@ -0,0 +1,120 @@
#include "uninstaller_page.h"
#include "ui_uninstallerpage.h"
UninstallerPage::~UninstallerPage()
{
delete ui;
delete loadingMovie;
}
UninstallerPage::UninstallerPage(QWidget *parent) :
QWidget(parent),
tm(ToolManager::ins()),
icon(QIcon(QString(":/static/themes/%1/img/package.svg").arg(AppManager::ins()->getThemeName()))),
loadingMovie(new QMovie(QString(":/static/themes/%1/img/loading.gif").arg(AppManager::ins()->getThemeName()))),
ui(new Ui::UninstallerPage)
{
ui->setupUi(this);
init();
}
void UninstallerPage::init()
{
ui->loading->setMovie(loadingMovie);
loadingMovie->start();
ui->loading->hide();
ui->notFoundWidget->hide();
QtConcurrent::run(this, &UninstallerPage::loadPackages);
connect(tm, &ToolManager::uninstallFinished, this, &UninstallerPage::loadPackages);
connect(tm, &ToolManager::uninstallStarted, this, &UninstallerPage::uninstallStarted);
}
void UninstallerPage::loadPackages()
{
uninstallStarted();
// clear items
ui->packagesList->clear();
foreach (QString package, tm->getPackages())
{
QListWidgetItem *item = new QListWidgetItem(QIcon::fromTheme(package, icon), QString(" %1").arg(package));
item->setCheckState(Qt::Unchecked);
ui->packagesList->addItem(item);
}
setAppCount();
ui->packagesList->setEnabled(true);
ui->packageSearch->setEnabled(true);
ui->uninstallBtn->show();
ui->packageSearch->clear();
ui->loading->hide();
}
void UninstallerPage::setAppCount()
{
int count = ui->packagesList->count();
ui->packagesTitle->setText(
tr("System Installed Packages (%1)")
.arg(QString::number(count)));
ui->notFoundWidget->setVisible(! count);
ui->packagesList->setVisible(count);
}
QStringList UninstallerPage::getSelectedPackages()
{
QStringList selectedPackages = {};
for (int i = 0; i < ui->packagesList->count(); i++)
{
QListWidgetItem *item = ui->packagesList->item(i);
if(item->checkState() == Qt::Checked)
selectedPackages << item->text().trimmed();
}
return selectedPackages;
}
void UninstallerPage::on_uninstallBtn_clicked()
{
QStringList selectedPackages = getSelectedPackages();
if(! selectedPackages.isEmpty())
{
QtConcurrent::run([selectedPackages]() -> void {
ToolManager::ins()->uninstallPackages(selectedPackages);
});
}
}
void UninstallerPage::uninstallStarted()
{
ui->packagesList->setEnabled(false);
ui->packageSearch->setEnabled(false);
ui->uninstallBtn->hide();
ui->loading->show();
}
void UninstallerPage::on_packageSearch_textChanged(const QString &val)
{
// Get matches items
QList<QListWidgetItem*> matches = ui->packagesList->findItems(val, Qt::MatchFlag::MatchContains);
// All items hide
for (int i = 0; i < ui->packagesList->count(); ++i)
ui->packagesList->item(i)->setHidden(true);
// Matches items show
foreach (QListWidgetItem* item, matches)
item->setHidden(false);
}

View File

@@ -0,0 +1,44 @@
#ifndef UNINSTALLERPAGE_H
#define UNINSTALLERPAGE_H
#include <QWidget>
#include <QListWidgetItem>
#include <QMovie>
#include <QtConcurrent>
#include "Managers/tool_manager.h"
#include "Managers/app_manager.h"
namespace Ui {
class UninstallerPage;
}
class UninstallerPage : public QWidget
{
Q_OBJECT
public:
explicit UninstallerPage(QWidget *parent = 0);
~UninstallerPage();
public slots:
void uninstallStarted();
private slots:
void init();
void setAppCount();
void on_packageSearch_textChanged(const QString &val);
void on_uninstallBtn_clicked();
QStringList getSelectedPackages();
void loadPackages();
private:
Ui::UninstallerPage *ui;
private:
ToolManager *tm;
QIcon icon;
QMovie *loadingMovie;
};
#endif // UNINSTALLERPAGE_H

View File

@@ -0,0 +1,292 @@
<?xml version="1.0" encoding="UTF-8"?>
<ui version="4.0">
<class>UninstallerPage</class>
<widget class="QWidget" name="UninstallerPage">
<property name="geometry">
<rect>
<x>0</x>
<y>0</y>
<width>916</width>
<height>553</height>
</rect>
</property>
<property name="windowTitle">
<string notr="true"/>
</property>
<layout class="QVBoxLayout" name="verticalLayout_2">
<property name="spacing">
<number>0</number>
</property>
<property name="leftMargin">
<number>10</number>
</property>
<property name="topMargin">
<number>10</number>
</property>
<property name="rightMargin">
<number>0</number>
</property>
<property name="bottomMargin">
<number>0</number>
</property>
<item>
<widget class="QWidget" name="verticalWidget" native="true">
<property name="styleSheet">
<string notr="true"/>
</property>
<layout class="QGridLayout" name="gridLayout">
<property name="leftMargin">
<number>30</number>
</property>
<property name="topMargin">
<number>0</number>
</property>
<property name="rightMargin">
<number>30</number>
</property>
<property name="bottomMargin">
<number>20</number>
</property>
<property name="spacing">
<number>5</number>
</property>
<item row="2" column="0" colspan="2">
<widget class="QListWidget" name="packagesList">
<property name="font">
<font>
<family>Ubuntu</family>
<pointsize>10</pointsize>
</font>
</property>
<property name="focusPolicy">
<enum>Qt::NoFocus</enum>
</property>
<property name="styleSheet">
<string notr="true"/>
</property>
<property name="autoScrollMargin">
<number>10</number>
</property>
<property name="editTriggers">
<set>QAbstractItemView::NoEditTriggers</set>
</property>
<property name="selectionMode">
<enum>QAbstractItemView::NoSelection</enum>
</property>
<property name="selectionBehavior">
<enum>QAbstractItemView::SelectRows</enum>
</property>
<property name="iconSize">
<size>
<width>20</width>
<height>20</height>
</size>
</property>
<property name="textElideMode">
<enum>Qt::ElideMiddle</enum>
</property>
<property name="spacing">
<number>4</number>
</property>
<property name="uniformItemSizes">
<bool>false</bool>
</property>
</widget>
</item>
<item row="3" column="0" colspan="2">
<spacer name="verticalSpacer">
<property name="orientation">
<enum>Qt::Vertical</enum>
</property>
<property name="sizeType">
<enum>QSizePolicy::Fixed</enum>
</property>
<property name="sizeHint" stdset="0">
<size>
<width>20</width>
<height>10</height>
</size>
</property>
</spacer>
</item>
<item row="4" column="0" colspan="2" alignment="Qt::AlignHCenter">
<widget class="QPushButton" name="uninstallBtn">
<property name="enabled">
<bool>true</bool>
</property>
<property name="font">
<font>
<family>Ubuntu</family>
</font>
</property>
<property name="cursor">
<cursorShape>PointingHandCursor</cursorShape>
</property>
<property name="focusPolicy">
<enum>Qt::NoFocus</enum>
</property>
<property name="styleSheet">
<string notr="true"/>
</property>
<property name="text">
<string>Uninstall Selected</string>
</property>
</widget>
</item>
<item row="1" column="0" colspan="2">
<widget class="QWidget" name="notFoundWidget" native="true">
<property name="sizePolicy">
<sizepolicy hsizetype="Preferred" vsizetype="Expanding">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="minimumSize">
<size>
<width>0</width>
<height>200</height>
</size>
</property>
<property name="maximumSize">
<size>
<width>16777215</width>
<height>200</height>
</size>
</property>
<property name="styleSheet">
<string notr="true"/>
</property>
<layout class="QVBoxLayout" name="notFoundLayout">
<property name="spacing">
<number>0</number>
</property>
<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 alignment="Qt::AlignHCenter|Qt::AlignBottom">
<widget class="QLabel" name="label">
<property name="text">
<string>Not Found Installed Packages</string>
</property>
</widget>
</item>
</layout>
</widget>
</item>
<item row="0" column="0" colspan="2">
<widget class="QWidget" name="horizontalWidget" native="true">
<property name="sizePolicy">
<sizepolicy hsizetype="Expanding" vsizetype="Minimum">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<layout class="QHBoxLayout" name="horizontalLayout">
<property name="spacing">
<number>5</number>
</property>
<property name="leftMargin">
<number>15</number>
</property>
<property name="topMargin">
<number>0</number>
</property>
<property name="rightMargin">
<number>20</number>
</property>
<property name="bottomMargin">
<number>0</number>
</property>
<item alignment="Qt::AlignLeft">
<widget class="QLabel" name="packagesTitle">
<property name="sizePolicy">
<sizepolicy hsizetype="Expanding" vsizetype="Preferred">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="font">
<font>
<family>Ubuntu</family>
<pointsize>11</pointsize>
<italic>false</italic>
</font>
</property>
<property name="styleSheet">
<string notr="true"/>
</property>
<property name="text">
<string>System Installed Packages</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>
<item alignment="Qt::AlignRight|Qt::AlignVCenter">
<widget class="QLineEdit" name="packageSearch">
<property name="minimumSize">
<size>
<width>170</width>
<height>0</height>
</size>
</property>
<property name="maximumSize">
<size>
<width>170</width>
<height>16777215</height>
</size>
</property>
<property name="font">
<font>
<pointsize>10</pointsize>
</font>
</property>
<property name="focusPolicy">
<enum>Qt::StrongFocus</enum>
</property>
<property name="styleSheet">
<string notr="true"/>
</property>
<property name="placeholderText">
<string>Search...</string>
</property>
</widget>
</item>
</layout>
</widget>
</item>
<item row="5" column="0" colspan="2" alignment="Qt::AlignHCenter">
<widget class="QLabel" name="loading">
<property name="text">
<string/>
</property>
</widget>
</item>
</layout>
</widget>
</item>
</layout>
</widget>
<resources/>
<connections/>
</ui>

Some files were not shown because too many files have changed in this diff Show More