Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
23 changes: 23 additions & 0 deletions main.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
#include <QQmlApplicationEngine>
#include <QQmlContext>
#include <QSystemTrayIcon>
#include <QApplication>

#include <tray.h>

int main(int argc, char *argv[])
{
QCoreApplication::setAttribute(Qt::AA_EnableHighDpiScaling);

QApplication app(argc, argv);

QQmlApplicationEngine engine;
Tray * systemTray = new Tray();
QQmlContext * context = engine.rootContext();

context->setContextProperty("systemTray", systemTray);

engine.load(QUrl(QStringLiteral("qrc:/main.qml")));

return app.exec();
}
215 changes: 215 additions & 0 deletions main.qml
Original file line number Diff line number Diff line change
@@ -0,0 +1,215 @@
import QtQuick 2.0
import QtQuick.Window 2.15
import QtMultimedia 5.15
import QtQuick.Controls 2.12
import QtQuick.Dialogs 1.3


ApplicationWindow {
id:root
visible: true
width: 640
height: 480
title: qsTr("Hello World")

property int selectedIndex: -1


MediaPlayer {
id: player;
volume: volumeSlider.volume
source: url
playlist: Playlist{
id:playlist
}
}

ListView {
id:listview
width:parent.width/2
height: parent.height
anchors.left: parent.left
anchors.bottom: parent.bottom
model: playlist;
spacing: 5
delegate: Rectangle{
width: listview.width
border.color: (model.index == root.selectedIndex) ? "red" : "gray"
height: 25
Text {
id: songUrl
text: source
visible: true
}
Text {
id: songname
text: source
}
MouseArea{
id:delegatemousearea
anchors.fill:parent
onClicked: {
root.selectedIndex = model.index
}
onDoubleClicked: {
playlist.moveItem(root.selectedIndex,0)
playlist.previous()
player.play()
}
}
}
}

Label{
id:label
anchors.bottom: progresstime.top
anchors.left: add.right
text: player.metaData.title + " " + player.metaData.albumArtist
}
Image {
id: songImage
height: parent.height-next.height-add.height-label.height-progresstime.height
width: parent.width-listview.width
anchors.bottom: label.top
anchors.right: pause.right
source: (player.metaData.posterUrl!=="undefind")?"qrc:/png-transparent-color-drawing-headphones-illustration-musical-note-game-photography-stage.png":player.metaData.posterUrl
}
FileDialog{
id:add_File
nameFilters: ["Song files(*.mp3)"]
onAccepted: {
playlist.addItem(fileUrl);
}
}

Button{
id:add
text: "add"
anchors.bottom: privious.top
anchors.right: privious.right
anchors.bottomMargin: 5
onClicked: {
add_File.open()
}
}
Button{
id:privious
text:"privious"
anchors.right: play.left
anchors.bottom: parent.bottom
anchors.rightMargin: 5
onClicked: {
playlist.previous();
}
}

Button{
id:next
text: "next"
anchors.right: parent.right
anchors.bottom: parent.bottom
anchors.rightMargin: 5
onClicked: {
playlist.next();
}
}
Button{
id:play
text: "play"
anchors.right: pause.left
anchors.rightMargin: 5
anchors.bottom: parent.bottom
onClicked: {
player.play();
}
}
Button{
id:pause
text: "pause"
anchors.right: next.left
anchors.rightMargin: 5
anchors.bottom: parent.bottom
onClicked: {
player.pause();
}
}
Slider {
id: volumeSlider
anchors.left: add.right
anchors.bottom: add.bottom
anchors.leftMargin: 5
property real volume: QtMultimedia.convertVolume(volumeSlider.value,
QtMultimedia.LogarithmicVolumeScale,
QtMultimedia.LinearVolumeScale)
}
Slider{
id:progresstime
anchors.bottom: volumeSlider.top
anchors.left: add.left
anchors.right: next.right
from: 0
to: player.duration
stepSize: 1000

onPressedChanged: {
if (!pressed && player.seekable)
player.seek(progresstime.value)
}

Connections{
target: player
onPositionChanged:{
progresstime.value=player.position
if(progresstime.value==0 && root.visibility === Window.Hidden)
systemTray.messege("Сейчас играет",player.metaData.title)
}
}

}

property bool ignoreCheck: false

/* С помощью объекта Connections
* Устанавливаем соединение с классом системного трея
* */
Connections {
target: systemTray
// Сигнал - показать окно
onSignalShow: {
root.show();
}

// Сигнал - закрыть приложения игнорируя чек-бокс
onSignalQuit: {
ignoreCheck = true
close();
}

// Свернуть/развернуть окно через клик по системному трею
onSignalIconActivated: {
if(root.visibility == Window.Hidden) {
root.show()
} else {
root.hide()
}
}
}


// Обработчик события закрытия окна
onClosing: {
/* Если чекбокс не должен игнорироваться и он активен,
* то скрываем приложение.
* В противном случае закрываем приложение
* */
if(ignoreCheck === false){
close.accepted = false
root.hide()
} else {
// Завершаем приложение
Qt.quit()
}
}

}

Binary file added play-button.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
7 changes: 7 additions & 0 deletions qml.qrc
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
<RCC>
<qresource prefix="/">
<file>main.qml</file>
<file>play-button.png</file>
<file>png-transparent-color-drawing-headphones-illustration-musical-note-game-photography-stage.png</file>
</qresource>
</RCC>
59 changes: 59 additions & 0 deletions tray.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,59 @@
#include "tray.h"
#include <QMenu>
#include <QSystemTrayIcon>

Tray::Tray(QObject *parent) : QObject(parent)
{

// Создаём контекстное меню с двумя пунктами
QMenu *trayIconMenu = new QMenu();

QAction * viewWindow = new QAction(trUtf8("Развернуть окно"), this);
QAction * quitAction = new QAction(trUtf8("Выход"), this);

/* подключаем сигналы нажатий на пункты меню к соответсвующим сигналам для QML.
* */
connect(viewWindow, &QAction::triggered, this, &Tray::signalShow);
connect(quitAction, &QAction::triggered, this, &Tray::signalQuit);

trayIconMenu->addAction(viewWindow);
trayIconMenu->addAction(quitAction);

/* Инициализируем иконку трея, устанавливаем иконку,
* а также задаем всплывающую подсказку
* */
trayIcon = new QSystemTrayIcon();
trayIcon->setContextMenu(trayIconMenu);
trayIcon->setIcon(QIcon(":/play-button.png"));
trayIcon->show();
trayIcon->setToolTip("Tray Program" "\n"
"Работа со сворачиванием программы трей");

/* Также подключаем сигнал нажатия на иконку к обработчику
* данного нажатия
* */
connect(trayIcon, SIGNAL(activated(QSystemTrayIcon::ActivationReason)),
this, SLOT(iconActivated(QSystemTrayIcon::ActivationReason)));
}

/* Метод, который обрабатывает нажатие на иконку приложения в трее
* */
void Tray::iconActivated(QSystemTrayIcon::ActivationReason reason)
{
switch (reason){
case QSystemTrayIcon::Trigger:
// В случае сигнала нажатия на иконку трея вызываем сигнал в QML слой
emit signalIconActivated();
break;
default:
break;
}
}

void Tray::hideIconTray()
{
trayIcon->hide();
}
void Tray::messege(QString title,QString messege){
trayIcon->showMessage(title,messege,QSystemTrayIcon::Information,500);
}
37 changes: 37 additions & 0 deletions tray.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
#ifndef TRAY_H
#define TRAY_H

#include <QQuickItem>
#include <QObject>
#include <QAction>
#include <QSystemTrayIcon>
#include <QApplication>

class Tray : public QObject
{
Q_OBJECT
public:
explicit Tray(QObject *parent = 0);

// Сигналы от системного трея
signals:
void signalIconActivated();
void signalShow();
void signalQuit();

private slots:
/* Слот, который будет принимать сигнал от события
* нажатия на иконку приложения в трее
*/
void iconActivated(QSystemTrayIcon::ActivationReason reason);

public slots:
void hideIconTray();
void messege(QString title,QString messege);

private:
/* Объявляем объект будущей иконки приложения для трея */
QSystemTrayIcon * trayIcon;
};

#endif // TRAY_H