Added system tray icon and number, preferences, debug,

This commit is contained in:
Ximi1970
2020-01-22 23:14:46 +01:00
parent 49d05884d6
commit 2ba2bb9ce8
29 changed files with 2730 additions and 380 deletions

View File

@@ -1,3 +1,4 @@
Native messaging
https://developer.mozilla.org/en-US/docs/Mozilla/Add-ons/WebExtensions/Native_messaging

View File

@@ -125,15 +125,24 @@ message("Version: "$$VERSION_MAJOR"."$$VERSION_MINOR"."$$VERSION_PATCH)
SOURCES += \
main.cpp \
mainwindow.cpp \
systrayxlink.cpp
systrayxlink.cpp \
systrayxicon.cpp \
systrayx.cpp \
debugwidget.cpp \
preferencesdialog.cpp \
preferences.cpp
HEADERS += \
mainwindow.h \
systrayxlink.h
systrayxlink.h \
systrayxicon.h \
systrayx.h \
debugwidget.h \
preferencesdialog.h \
preferences.h
FORMS += \
mainwindow.ui
debugwidget.ui \
preferences.ui
# Default rules for deployment.
qnx: target.path = /tmp/$${TARGET}/bin

View File

@@ -1,5 +1,6 @@
<RCC>
<qresource prefix="/">
<file>files/icons/SysTray-X.png</file>
<file>files/icons/blank-icon.png</file>
</qresource>
</RCC>

View File

@@ -0,0 +1,130 @@
#include "debugwidget.h"
#include "ui_debugwidget.h"
/*
* Local includes
*/
#include "preferences.h"
/*
* Qt includes
*/
/*
* Constructor
*/
DebugWidget::DebugWidget( Preferences *pref, QWidget *parent ) : QWidget( parent ), m_ui( new Ui::DebugWidget )
{
m_ui->setupUi( this );
/*
* Store the preferences
*/
m_pref = pref;
}
/*
* Set the debug message
*/
void DebugWidget::setDebugMessage( QString message )
{
m_ui->messageLabel->setText( message );
}
/*
* Set the raw data length
*/
void DebugWidget::setRawDataLength( int length )
{
m_ui->rawDataLengthLabel->setText( QString::number( length ) );
}
/*
* Set the raw received message
*/
void DebugWidget::setErrorDataMessage( const QString &message )
{
m_ui->rawDataLabel->setText( message );
}
/*
* Set the number of unread mail
*/
void DebugWidget::setUnreadMail( int unread )
{
m_ui->unreadMailLabel->setText( QString::number( unread ) );
}
/*
* Set the link error message
*/
void DebugWidget::setError( const QString &error )
{
m_ui->errorLabel->setText( error );
}
/*
* Handle a debug state change signal
*/
void DebugWidget::slotDebugChange()
{
this->setVisible( m_pref->getDebug() );
}
/*
* Handle a debug message signal
*/
void DebugWidget::slotDebugMessage( QString message )
{
setDebugMessage( message );
}
/*
* Handle received message length
*/
void DebugWidget::slotReceivedMessageLength( qint32 msglen )
{
setRawDataLength( msglen );
}
/*
* Display received message
*/
void DebugWidget::slotReceivedMessage( QByteArray message )
{
setErrorDataMessage( QString( message ) );
/*
* Reply
*/
// QByteArray reply = QString( "\"Hallo other world!\"" ).toUtf8();
// emit signalWriteMessage( reply );
}
/*
* Handle unread mail signal
*/
void DebugWidget::slotUnreadMail( int unread_mail )
{
setUnreadMail( unread_mail );
}
/*
* Handle a receive error
*/
void DebugWidget::slotReceiveError( QString error )
{
setError( error );
}

140
app/SysTray-X/debugwidget.h Normal file
View File

@@ -0,0 +1,140 @@
#ifndef DEBUGWIDGET_H
#define DEBUGWIDGET_H
/*
* Local includes
*/
/*
* Qt includes
*/
#include <QWidget>
/*
* Predefines
*/
class Preferences;
/*
* Namespace
*/
namespace Ui {
class DebugWidget;
}
/**
* @brief The DebugWidget class
*/
class DebugWidget : public QWidget
{
Q_OBJECT
public:
/**
* @brief DebugWidget. Constructor.
*
* @param parent My parent.
*/
explicit DebugWidget( Preferences *pref, QWidget *parent = nullptr );
/**
* @brief setDebugMessage. Display a debug message.
*
* @param message The message to display.
*/
void setDebugMessage( QString message );
/**
* @brief setRawDataLength. Display the error data length.
*
* @param length The raw data length.
*/
void setRawDataLength( int length );
/**
* @brief setRswDataMessage. Display the raw data.
*
* @param message The raw data messsage.
*/
void setErrorDataMessage( const QString &message );
/**
* @brief setUnreadMail. Set the number of unread mails.
*
* @param unread The number of unread mails.
*/
void setUnreadMail( int unread );
/**
* @brief setError. Set the error message.
*
* @param error The error message.
*/
void setError( const QString &error );
signals:
/**
* @brief signalWriteMessage
*
* @param message
*/
void signalWriteMessage( QByteArray message );
public slots:
/**
* @brief slotDebugChange. The debug state changed.
*/
void slotDebugChange();
/**
* @brief slotReceivedMessageLength
*
* @param msglen
*/
void slotDebugMessage( QString message );
/**
* @brief slotReceivedMessageLength
*
* @param msglen
*/
void slotReceivedMessageLength( qint32 msglen );
/**
* @brief slotReceivedMessage
*
* @param message
*/
void slotReceivedMessage( QByteArray message );
/**
* @brief slotSetUnreadMail. Slot for handling unread mail signals.
*
* @param unread_mail The number of unread mails.
*/
void slotUnreadMail( int unread_mail );
/**
* @brief slotReceiveError. Handle receive error signal.
*
* @param error Error message.
*/
void slotReceiveError( QString error );
private:
/**
* @brief m_ui. Pointer to the widget.
*/
Ui::DebugWidget *m_ui;
/**
* @brief m_pref. Pointer to ther preferences.
*/
Preferences *m_pref;
};
#endif // DEBUGWIDGET_H

View File

@@ -0,0 +1,99 @@
<?xml version="1.0" encoding="UTF-8"?>
<ui version="4.0">
<class>DebugWidget</class>
<widget class="QWidget" name="DebugWidget">
<property name="geometry">
<rect>
<x>0</x>
<y>0</y>
<width>400</width>
<height>300</height>
</rect>
</property>
<property name="windowTitle">
<string>SysTray-X Debug</string>
</property>
<widget class="QWidget" name="layoutWidget">
<property name="geometry">
<rect>
<x>10</x>
<y>10</y>
<width>381</width>
<height>281</height>
</rect>
</property>
<layout class="QGridLayout" name="gridLayout">
<item row="5" column="0">
<widget class="QLabel" name="rawDataLengthLabel">
<property name="text">
<string>0</string>
</property>
</widget>
</item>
<item row="3" column="0" colspan="2">
<widget class="QLabel" name="errorLabel">
<property name="text">
<string/>
</property>
</widget>
</item>
<item row="1" column="0">
<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="1">
<widget class="QLabel" name="unreadMailLabel">
<property name="text">
<string>0</string>
</property>
</widget>
</item>
<item row="1" 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="1">
<widget class="QLabel" name="rawDataLabel">
<property name="text">
<string/>
</property>
</widget>
</item>
<item row="0" column="0">
<widget class="QLabel" name="unreadMailTextLabel">
<property name="text">
<string>Unread mail:</string>
</property>
</widget>
</item>
<item row="2" column="0" colspan="2">
<widget class="QLabel" name="messageLabel">
<property name="text">
<string/>
</property>
</widget>
</item>
</layout>
</widget>
</widget>
<resources/>
<connections/>
</ui>

View File

@@ -1 +1 @@
The icon used here is taken from the "Miscellany Web icons" set by Maria & Guillem (https://www.iconfinder.com/andromina), and is used under the Creative Commons (Attribution 3.0 Unported) license.
The SysTray-X / mail icon used here is taken from the "Miscellany Web icons" set by Maria & Guillem (https://www.iconfinder.com/andromina), and is used under the Creative Commons (Attribution 3.0 Unported) license.

Binary file not shown.

After

Width:  |  Height:  |  Size: 22 KiB

View File

@@ -1,11 +1,17 @@
#include "mainwindow.h"
/*
* Local includes
*/
#include "systrayx.h"
/*
* Qt includes
*/
#include <QApplication>
int main(int argc, char *argv[])
{
QApplication a(argc, argv);
MainWindow w;
w.show();
SysTrayX systrayx;
return a.exec();
}

View File

@@ -1,38 +0,0 @@
#include "mainwindow.h"
#include "ui_mainwindow.h"
MainWindow::MainWindow(QWidget *parent) :
QMainWindow(parent),
ui(new Ui::MainWindow)
{
ui->setupUi(this);
connect( &m_systray_x_link, &SysTrayXLink::signalReceivedMessageLength, this, &MainWindow::slotReceivedMessageLength );
connect( &m_systray_x_link, &SysTrayXLink::signalReceivedMessage, this, &MainWindow::slotReceivedMessage );
connect( this, &MainWindow::signalWriteMessage, &m_systray_x_link, &SysTrayXLink::slotLinkWrite );
}
MainWindow::~MainWindow()
{
delete ui;
}
void MainWindow::slotReceivedMessageLength( qint32 msglen )
{
ui->label_length->setText(QString::number( msglen ) );
}
void MainWindow::slotReceivedMessage( QByteArray message )
{
ui->label_message->setText( QString::fromStdString( message.toStdString() ) );
/*
* Reply
*/
QByteArray reply = QString( "\"Hallo other world!\"" ).toUtf8();
emit signalWriteMessage( reply );
}

View File

@@ -1,60 +0,0 @@
#ifndef MAINWINDOW_H
#define MAINWINDOW_H
/*
* Local includes
*/
#include "systrayxlink.h"
/*
* Qt includes
*/
#include <QObject>
#include <QMainWindow>
namespace Ui {
class MainWindow;
}
class MainWindow : public QMainWindow
{
Q_OBJECT
public:
explicit MainWindow(QWidget *parent = nullptr);
~MainWindow();
private slots:
/**
* @brief slotReceivedMessageLength
*
* @param msglen
*/
void slotReceivedMessageLength( qint32 msglen );
/**
* @brief slotReceivedMessage
*
* @param message
*/
void slotReceivedMessage( QByteArray message );
signals:
/**
* @brief signalWriteMessage
*
* @param message
*/
void signalWriteMessage( QByteArray message );
private:
Ui::MainWindow *ui;
SysTrayXLink m_systray_x_link;
};
#endif // MAINWINDOW_H

View File

@@ -1,67 +0,0 @@
<?xml version="1.0" encoding="UTF-8"?>
<ui version="4.0">
<class>MainWindow</class>
<widget class="QMainWindow" name="MainWindow">
<property name="geometry">
<rect>
<x>0</x>
<y>0</y>
<width>400</width>
<height>300</height>
</rect>
</property>
<property name="windowTitle">
<string>MainWindow</string>
</property>
<widget class="QWidget" name="centralWidget">
<widget class="QLabel" name="label_length">
<property name="geometry">
<rect>
<x>50</x>
<y>10</y>
<width>271</width>
<height>51</height>
</rect>
</property>
<property name="text">
<string>Data here</string>
</property>
</widget>
<widget class="QLabel" name="label_message">
<property name="geometry">
<rect>
<x>50</x>
<y>80</y>
<width>271</width>
<height>51</height>
</rect>
</property>
<property name="text">
<string>Data here</string>
</property>
</widget>
</widget>
<widget class="QMenuBar" name="menuBar">
<property name="geometry">
<rect>
<x>0</x>
<y>0</y>
<width>400</width>
<height>30</height>
</rect>
</property>
</widget>
<widget class="QToolBar" name="mainToolBar">
<attribute name="toolBarArea">
<enum>TopToolBarArea</enum>
</attribute>
<attribute name="toolBarBreak">
<bool>false</bool>
</attribute>
</widget>
<widget class="QStatusBar" name="statusBar"/>
</widget>
<layoutdefault spacing="6" margin="11"/>
<resources/>
<connections/>
</ui>

View File

@@ -0,0 +1,137 @@
#include "preferences.h"
/**
* @brief Preferences. Constructor.
*/
Preferences::Preferences( QObject *parent ) : QObject( parent )
{
/*
* Initialize
*/
m_app_pref_changed = false;
m_icon_type = PREF_BLANK_ICON;
m_icon_mime = "image/png";
m_icon_data = QByteArray();
m_debug = false;
}
/*
* Get the icon type.
*/
Preferences::IconType Preferences::getIconType() const
{
return m_icon_type;
}
/*
* Get the icon mime.
*/
bool Preferences::getAppPrefChanged() const
{
return m_app_pref_changed;
}
/*
* Control the sending of preferences changes to the add-on
*/
void Preferences::setAppPrefChanged( bool state )
{
if( m_app_pref_changed != state )
{
m_app_pref_changed = state;
}
}
/*
* Set the icon type.
*/
void Preferences::setIconType( IconType icon_type )
{
if( m_icon_type != icon_type)
{
m_icon_type = icon_type;
/*
* Tell the world the new preference
*/
emit signalIconTypeChange();
}
}
/*
* Get the icon mime.
*/
const QString& Preferences::getIconMime() const
{
return m_icon_mime;
}
/*
* Set the icon mime.
*/
void Preferences::setIconMime( const QString& icon_mime )
{
m_icon_mime = icon_mime;
}
/*
* Get the icon data.
*/
const QByteArray& Preferences::getIconData() const
{
return m_icon_data;
}
/*
* Set the icon data.
*/
void Preferences::setIconData( const QByteArray& icon_data )
{
if( m_icon_data != icon_data )
{
m_icon_data = icon_data;
/*
* Tell the world the new preference
*/
emit signalIconDataChange();
}
}
/*
* Get the icon data.
*/
bool Preferences::getDebug() const
{
return m_debug;
}
/*
* Set the icon data.
*/
void Preferences::setDebug( bool state )
{
if( m_debug != state )
{
m_debug = state;
/*
* Tell the world the new preference
*/
emit signalDebugChange();
}
}

155
app/SysTray-X/preferences.h Normal file
View File

@@ -0,0 +1,155 @@
#ifndef PREFERENCES_H
#define PREFERENCES_H
/*
* Local includes
*/
/*
* Qt includes
*/
#include <QObject>
#include <QString>
#include <QByteArray>
/**
* @brief The Preferences class. Class to hold the preferences.
*/
class Preferences : public QObject
{
Q_OBJECT
public:
/*
* Icon types
*/
enum IconType {
PREF_BLANK_ICON = 0,
PREF_NEWMAIL_ICON,
PREF_CUSTOM_ICON
};
public:
/**
* @brief Preferences. Constructor.
*/
Preferences( QObject *parent = nullptr );
/**
* @brief getAppPrefChanged. Control for sending changes to the add-on.
*
* @return The state
*/
bool getAppPrefChanged() const;
/**
* @brief setAppPrefChanged. Control for sending changes to the add-on.
*
* @param state The state
*/
void setAppPrefChanged( bool state );
/**
* @brief getIconType. Get the icon type.
*
* @return The icon type.
*/
IconType getIconType() const;
/**
* @brief setIconType. Set the icon type.
*
* @param The icon type.
*/
void setIconType( IconType icon_type );
/**
* @brief getIconMime. Get the icon mime.
*
* @return The icon mime.
*/
const QString& getIconMime() const;
/**
* @brief setIconMime. Set the icon mime.
*
* @param The icon mime.
*/
void setIconMime( const QString& icon_mime );
/**
* @brief getIconData. Get the icon data.
*
* @return The icon data.
*/
const QByteArray& getIconData() const;
/**
* @brief setIconData. Set the icon data.
*
* @param The icon data.
*/
void setIconData( const QByteArray& icon_data );
/**
* @brief getDebug. Get the debug windows state.
*
* @return The state.
*/
bool getDebug() const;
/**
* @brief setDebug. Set the debug windows state.
*
* @param The state.
*/
void setDebug( bool state );
signals:
/**
* @brief signalIconTypeChange. Signal a icon type change.
*/
void signalIconTypeChange();
/**
* @brief signalIconDataChange. Signal a icon data change.
*/
void signalIconDataChange();
/**
* @brief signalDebugChange. Signal a debug state change.
*/
void signalDebugChange();
private:
/**
* @brief m_app_pref_changed. Control for sending changes to the add-on.
*/
bool m_app_pref_changed;
/**
* @brief m_icon_type. Selected icon type.
*/
IconType m_icon_type;
/**
* @brief m_icon_mime. Selected icon mime.
*/
QString m_icon_mime;
/**
* @brief m_icon_data. Binary data icon image.
*/
QByteArray m_icon_data;
/**
* @brief m_debug. Display debug window.
*/
bool m_debug;
};
#endif // PREFERENCES_H

View File

@@ -0,0 +1,207 @@
<?xml version="1.0" encoding="UTF-8"?>
<ui version="4.0">
<class>PreferencesDialog</class>
<widget class="QDialog" name="PreferencesDialog">
<property name="geometry">
<rect>
<x>0</x>
<y>0</y>
<width>553</width>
<height>544</height>
</rect>
</property>
<property name="windowTitle">
<string>SysTray-X Preferences</string>
</property>
<layout class="QGridLayout" name="gridLayout">
<item row="2" column="1">
<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="4" column="2">
<widget class="QDialogButtonBox" name="buttonBox">
<property name="orientation">
<enum>Qt::Horizontal</enum>
</property>
<property name="standardButtons">
<set>QDialogButtonBox::Cancel|QDialogButtonBox::Ok</set>
</property>
</widget>
</item>
<item row="4" column="0" colspan="2">
<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="0" column="1">
<widget class="QGroupBox" name="iconTypeGroupBox">
<property name="title">
<string>Mail notification icon</string>
</property>
<layout class="QVBoxLayout" name="verticalLayout_2">
<item>
<layout class="QVBoxLayout" name="verticalLayout">
<item>
<layout class="QHBoxLayout" name="horizontalLayout_3">
<property name="sizeConstraint">
<enum>QLayout::SetFixedSize</enum>
</property>
<item>
<widget class="QRadioButton" name="blankRadioButton">
<property name="text">
<string>Blank icon</string>
</property>
<property name="checked">
<bool>true</bool>
</property>
<attribute name="buttonGroup">
<string notr="true">iconTypeGroup</string>
</attribute>
</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>
</layout>
</item>
<item>
<layout class="QHBoxLayout" name="horizontalLayout_2">
<property name="sizeConstraint">
<enum>QLayout::SetFixedSize</enum>
</property>
<item>
<widget class="QRadioButton" name="newMailButton">
<property name="text">
<string>New mail icon</string>
</property>
<attribute name="buttonGroup">
<string notr="true">iconTypeGroup</string>
</attribute>
</widget>
</item>
<item>
<spacer name="horizontalSpacer">
<property name="orientation">
<enum>Qt::Horizontal</enum>
</property>
<property name="sizeHint" stdset="0">
<size>
<width>40</width>
<height>20</height>
</size>
</property>
</spacer>
</item>
</layout>
</item>
<item>
<layout class="QHBoxLayout" name="horizontalLayout">
<property name="sizeConstraint">
<enum>QLayout::SetMaximumSize</enum>
</property>
<item>
<widget class="QRadioButton" name="customRadioButton">
<property name="text">
<string>Custom icon</string>
</property>
<attribute name="buttonGroup">
<string notr="true">iconTypeGroup</string>
</attribute>
</widget>
</item>
<item>
<widget class="QLabel" name="imageLabel">
<property name="text">
<string/>
</property>
</widget>
</item>
<item>
<widget class="QPushButton" name="chooseCustomButton">
<property name="text">
<string>Choose</string>
</property>
<property name="flat">
<bool>false</bool>
</property>
</widget>
</item>
</layout>
</item>
</layout>
</item>
</layout>
</widget>
</item>
<item row="0" column="2">
<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="1" column="1">
<widget class="QCheckBox" name="debugWindowCheckBox">
<property name="text">
<string>Display debug window</string>
</property>
</widget>
</item>
</layout>
</widget>
<resources/>
<connections>
<connection>
<sender>buttonBox</sender>
<signal>rejected()</signal>
<receiver>PreferencesDialog</receiver>
<slot>reject()</slot>
<hints>
<hint type="sourcelabel">
<x>316</x>
<y>260</y>
</hint>
<hint type="destinationlabel">
<x>286</x>
<y>274</y>
</hint>
</hints>
</connection>
</connections>
<buttongroups>
<buttongroup name="iconTypeGroup"/>
</buttongroups>
</ui>

View File

@@ -0,0 +1,191 @@
#include "preferencesdialog.h"
#include "ui_preferences.h"
/*
* Local includes
*/
#include "systrayxlink.h"
/*
* Qt includes
*/
#include <QPixmap>
#include <QFileDialog>
#include <QMimeDatabase>
#include <QJsonDocument>
#include <QJsonObject>
/*
* Constructor
*/
PreferencesDialog::PreferencesDialog( SysTrayXLink *link, Preferences *pref, QWidget *parent ) : QDialog( parent ), m_ui( new Ui::PreferencesDialog )
{
m_ui->setupUi( this );
/*
* Store link adn preferences
*/
m_link = link;
m_pref = pref;
/*
* Set button Ids
*/
m_ui->iconTypeGroup->setId( m_ui->blankRadioButton, Preferences::PREF_BLANK_ICON );
m_ui->iconTypeGroup->setId( m_ui->newMailButton, Preferences::PREF_NEWMAIL_ICON );
m_ui->iconTypeGroup->setId( m_ui->customRadioButton, Preferences::PREF_CUSTOM_ICON );
/*
* Set defaults
*/
m_tmp_icon_data = QByteArray();
m_tmp_icon_mime = QString();
/*
* Signals and slots
*/
connect( m_ui->chooseCustomButton, &QPushButton::clicked, this, &PreferencesDialog::slotFileSelect );
connect( m_ui->buttonBox, &QDialogButtonBox::accepted, this, &PreferencesDialog::slotAccept );
}
/*
* Set the debug state
*/
void PreferencesDialog::setDebug( bool state )
{
m_ui->debugWindowCheckBox->setChecked( state );
}
/*
* Set the icon type
*/
void PreferencesDialog::setIconType( Preferences::IconType icon_type )
{
( m_ui->iconTypeGroup->button( icon_type ) )->setChecked( true );
}
/*
* Set the icon
*/
void PreferencesDialog::setIcon( const QString& icon_mime, const QByteArray& icon )
{
/*
* Store the new icon
*/
m_tmp_icon_mime = icon_mime;
m_tmp_icon_data = icon;
/*
* Display the new icon
*/
setIcon();
}
/*
* Set the icon
*/
void PreferencesDialog::setIcon()
{
/*
* Convert data to pixmap
*/
QPixmap pixmap;
pixmap.loadFromData( m_tmp_icon_data );
/*
* Display the icon
*/
m_ui->imageLabel->setPixmap( pixmap.scaledToHeight( m_ui->chooseCustomButton->size().height() ) );
}
/*
* Handle the accept signal
*/
void PreferencesDialog::slotAccept()
{
/*
* Settings changed by app
*/
m_pref->setAppPrefChanged( true );
/*
* Get all the selected values and store them in the preferences
*/
m_pref->setIconType( static_cast< Preferences::IconType >( m_ui->iconTypeGroup->checkedId() ) );
m_pref->setIconMime( m_tmp_icon_mime );
m_pref->setIconData( m_tmp_icon_data );
m_pref->setDebug( m_ui->debugWindowCheckBox->isChecked() );
/*
* Settings changed by app
*/
m_pref->setAppPrefChanged( false );
/*
* Tell the base
*/
QDialog::accept();
}
/*
* Handle the choose button
*/
void PreferencesDialog::slotFileSelect()
{
QFileDialog file_dialog( this, tr( "Open Image" ), "", tr( "Image Files (*.png *.jpg *.bmp)" ) );
if( file_dialog.exec() )
{
QFile file( file_dialog.selectedFiles()[ 0 ] );
file.open( QIODevice::ReadOnly );
m_tmp_icon_data = file.readAll();
file.close();
QMimeType type = QMimeDatabase().mimeTypeForData( m_tmp_icon_data );
m_tmp_icon_mime = type.name();
/*
* Display the icon
*/
setIcon();
}
}
/*
* Handle the debug change signal
*/
void PreferencesDialog::slotDebugChange()
{
setDebug( m_pref->getDebug() );
}
/*
* Handle the icon type change signal
*/
void PreferencesDialog::slotIconTypeChange()
{
setIconType( m_pref->getIconType() );
}
/*
* Handle the icon data change signal
*/
void PreferencesDialog::slotIconDataChange()
{
m_tmp_icon_mime = m_pref->getIconMime();
m_tmp_icon_data = m_pref->getIconData();
/*
* Display the icon
*/
setIcon();
}

View File

@@ -0,0 +1,143 @@
#ifndef PREFERENCESDIALOG_H
#define PREFERENCESDIALOG_H
/*
* Local includes
*/
#include "preferences.h"
/*
* Qt includes
*/
#include <QDialog>
#include <QByteArray>
/*
* Predefines
*/
class SysTrayXLink;
/*
* Namespace
*/
namespace Ui {
class PreferencesDialog;
}
/**
* @brief The PreferencesDialog class. Handles the preferences.
*/
class PreferencesDialog : public QDialog
{
Q_OBJECT
public:
/**
* @brief PreferencesDialog
*/
PreferencesDialog( SysTrayXLink *link, Preferences *pref, QWidget *parent = nullptr );
private:
/**
* @brief setDebug. Set the debug state.
*
* @param state The state.
*/
void setDebug( bool state );
/**
* @brief setIconType. Set the icon type.
*
* @param icon_type The icon type.
*/
void setIconType( Preferences::IconType icon_type );
/**
* @brief setIcon. Set the icon.
*
* @param icon The icon mime.
* @param icon The icon data.
*/
void setIcon( const QString& icon_mime, const QByteArray& icon );
/**
* @brief setIcon. Set the icon.
*/
void setIcon();
signals:
/**
* @brief signalDebugMessage. Signal a debug message.
*
* @param message The message.
*/
void signalDebugMessage( QString message );
/**
* @brief signalUpdateSysTray. Signal to update the system tray icon.
*/
void signalUpdateSysTrayIcon();
public slots:
/**
* @brief slotDebugChange. Slot for handling debug change signals.
*/
void slotDebugChange();
/**
* @brief slotIconTypeChange. Slot for handling icon type change signals.
*/
void slotIconTypeChange();
/**
* @brief slotIconDataChange. Slot for handling icon data change signals.
*/
void slotIconDataChange();
private slots:
/**
* @brief slotAccept. Store the preferences on the accept signal.
*/
void slotAccept();
/**
* @brief slotFileSelect. Handle the choose custom button click.
*/
void slotFileSelect();
private:
/**
* @brief m_ui. Pointer to the dialog.
*/
Ui::PreferencesDialog *m_ui;
/**
* @brief m_link. Pointer to the link.
*/
SysTrayXLink *m_link;
/**
* @brief m_pref. Pointer to the preferences storage.
*/
Preferences *m_pref;
/**
* @brief m_tmp_icon_mime. Temporary storage for icon mime.
*/
QString m_tmp_icon_mime;
/**
* @brief m_tmp_icon_data. Temporary storage for icon data.
*/
QByteArray m_tmp_icon_data;
};
#endif // PREFERENCESDIALOG_H

193
app/SysTray-X/systrayx.cpp Normal file
View File

@@ -0,0 +1,193 @@
#include "systrayx.h"
/*
* Local includes
*/
#include "debugwidget.h"
#include "preferencesdialog.h"
#include "systrayxlink.h"
#include "systrayxicon.h"
/*
* Qt includes
*/
#include <QCoreApplication>
#include <QMenu>
/*
* Constants
*/
const QString SysTrayX::JSON_PREF_REQUEST = "{\"preferences\":{}}";
/*
* Constructor
*/
SysTrayX::SysTrayX( QObject *parent ) : QObject( parent )
{
/*
* Setup preferences storage
*/
m_preferences = new Preferences();
/*
* Setup the link
*/
m_link = new SysTrayXLink( m_preferences );
/*
* Setup preferences dialog
*/
m_pref_dialog = new PreferencesDialog( m_link, m_preferences );
/*
* Setup tray icon
*/
createTrayIcon();
m_tray_icon->show();
/*
* Setup debug window
*/
m_debug = new DebugWidget( m_preferences );
if( m_preferences->getDebug() ) {
m_debug->show();
}
// connect( m_trayIcon, &QSystemTrayIcon::messageClicked, this, &SysTrayX::messageClicked);
connect( m_tray_icon, &QSystemTrayIcon::activated, this, &SysTrayX::iconActivated);
/*
* Connect debug link signals
*/
connect( m_link, &SysTrayXLink::signalReceivedMessageLength, m_debug, &DebugWidget::slotReceivedMessageLength );
connect( m_link, &SysTrayXLink::signalReceivedMessage, m_debug, &DebugWidget::slotReceivedMessage );
connect( m_link, &SysTrayXLink::signalUnreadMail, m_debug, &DebugWidget::slotUnreadMail );
connect( m_link, &SysTrayXLink::signalLinkReceiveError, m_debug, &DebugWidget::slotReceiveError );
connect( m_debug, &DebugWidget::signalWriteMessage, m_link, &SysTrayXLink::slotLinkWrite );
connect( m_pref_dialog, &PreferencesDialog::signalDebugMessage, m_debug, &DebugWidget::slotDebugMessage );
connect( m_tray_icon, &SysTrayXIcon::signalDebugMessage, m_debug, &DebugWidget::slotDebugMessage );
connect( m_link, &SysTrayXLink::signalDebugMessage, m_debug, &DebugWidget::slotDebugMessage );
/*
* Connect preferences signals
*/
connect( m_preferences, &Preferences::signalIconTypeChange, m_tray_icon, &SysTrayXIcon::slotIconTypeChange );
connect( m_preferences, &Preferences::signalIconDataChange, m_tray_icon, &SysTrayXIcon::slotIconDataChange );
connect( m_preferences, &Preferences::signalIconTypeChange, m_pref_dialog, &PreferencesDialog::slotIconTypeChange );
connect( m_preferences, &Preferences::signalIconDataChange, m_pref_dialog, &PreferencesDialog::slotIconDataChange );
connect( m_preferences, &Preferences::signalDebugChange, m_pref_dialog, &PreferencesDialog::slotDebugChange );
connect( m_preferences, &Preferences::signalIconTypeChange, m_link, &SysTrayXLink::slotIconTypeChange );
connect( m_preferences, &Preferences::signalIconDataChange, m_link, &SysTrayXLink::slotIconDataChange );
connect( m_preferences, &Preferences::signalDebugChange, m_link, &SysTrayXLink::slotDebugChange );
connect( m_preferences, &Preferences::signalDebugChange, m_debug, &DebugWidget::slotDebugChange );
/*
* Connect link signals
*/
connect( m_link, &SysTrayXLink::signalUnreadMail, m_tray_icon, &SysTrayXIcon::slotSetUnreadMail );
/*
* Request preferences from add-on
*/
getPreferences();
}
/*
* Send a preferences request
*/
void SysTrayX::getPreferences()
{
/*
* Request preferences from add-on
*/
QByteArray request = QString( SysTrayX::JSON_PREF_REQUEST ).toUtf8();
emit signalWriteMessage( request );
}
/*
* Handle a click on the system tray icon
*/
void SysTrayX::iconActivated( QSystemTrayIcon::ActivationReason reason )
{
switch (reason) {
case QSystemTrayIcon::Trigger:
case QSystemTrayIcon::DoubleClick:
case QSystemTrayIcon::MiddleClick:
break;
default:
;
}
}
/*
* Create the actions for the system tray icon menu
*/
void SysTrayX::createActions()
{
/*
m_minimizeAction = new QAction(tr("Mi&nimize"), this);
connect( m_minimizeAction, &QAction::triggered, this, &QWidget::hide );
m_maximizeAction = new QAction(tr("Ma&ximize"), this);
connect( m_maximizeAction, &QAction::triggered, this, &QWidget::showMaximized );
m_restoreAction = new QAction(tr("&Restore"), this);
connect( m_restoreAction, &QAction::triggered, this, &QWidget::showNormal );
*/
m_pref_action = new QAction(tr("&Preferences"), this);
connect( m_pref_action, &QAction::triggered, m_pref_dialog, &PreferencesDialog::showNormal );
m_quit_action = new QAction(tr("&Quit"), this);
connect( m_quit_action, &QAction::triggered, qApp, &QCoreApplication::quit );
}
/*
* Create the system tray icon
*/
void SysTrayX::createTrayIcon()
{
/*
* Setup menu actions
*/
createActions();
/*
* Setup menu
*/
m_tray_icon_menu = new QMenu();
// m_trayIconMenu->addAction( m_minimizeAction );
// m_trayIconMenu->addAction( m_maximizeAction );
// m_trayIconMenu->addAction( m_restoreAction );
m_tray_icon_menu->addAction( m_pref_action );
m_tray_icon_menu->addSeparator();
m_tray_icon_menu->addAction( m_quit_action );
/*
* Create system tray icon
*/
m_tray_icon = new SysTrayXIcon( m_link, m_preferences );
m_tray_icon->setContextMenu( m_tray_icon_menu );
/*
* Set icon
*/
m_tray_icon->setIconMime( m_preferences->getIconMime() );
m_tray_icon->setIconData( m_preferences->getIconData() );
m_tray_icon->setIconType( m_preferences->getIconType() );
}

119
app/SysTray-X/systrayx.h Normal file
View File

@@ -0,0 +1,119 @@
#ifndef SYSTRAYX_H
#define SYSTRAYX_H
/*
* Local includes
*/
#include "ui_debugwidget.h"
#include "preferences.h"
/*
* Qt includes
*/
#include <QObject>
#include <QSystemTrayIcon>
/*
* Predefines
*/
class QAction;
class DebugWidget;
class PreferencesDialog;
class SysTrayXIcon;
class SysTrayXLink;
/**
* @brief The SysTrayX class
*/
class SysTrayX : public QObject
{
Q_OBJECT
public:
static const QString JSON_PREF_REQUEST;
public:
/**
* @brief SysTrayX. Constructor.
*
* @param parent My parent.
*/
explicit SysTrayX( QObject *parent = nullptr );
private:
/**
* @brief SysTrayX::getPreferences
*/
void getPreferences();
/**
* @brief iconActivated
* @param reason
*/
void iconActivated( QSystemTrayIcon::ActivationReason reason );
/**
* @brief createTrayIcon. Create the system tray icon.
*/
void createTrayIcon();
/**
* @brief createActions. Create the menu actions.
*/
void createActions();
signals:
/**
* @brief signalWriteMessage
*
* @param message
*/
void signalWriteMessage( QByteArray message );
private slots:
private:
/**
* @brief m_preferences. Pointer to the preferences storage.
*/
Preferences *m_preferences;
/**
* @brief m_debug
*/
DebugWidget *m_debug;
/**
* @brief m_link. Pointer to the link object.
*/
SysTrayXLink *m_link;
/**
* @brief m_pref_dialog. Pointer to the preferences dialog.
*/
PreferencesDialog *m_pref_dialog;
/**
* @brief m_tray_icon. Pointer to the system tray icon.
*/
SysTrayXIcon *m_tray_icon;
/**
* @brief m_tray_icon_menu. Pointer to the tray icon menu.
*/
QMenu *m_tray_icon_menu;
/**
* @brief m_xxxx_action. Pointer to the menu actions.
*/
QAction *m_pref_action;
QAction *m_quit_action;
};
#endif // SYSTRAYX_H

View File

@@ -0,0 +1,184 @@
#include "systrayxicon.h"
/*
* Local includes
*/
#include "preferences.h"
/*
* System includes
*/
#include "systrayxlink.h"
/*
* Qt includes
*/
#include <QPainter>
/*
* Constructor
*/
SysTrayXIcon::SysTrayXIcon( SysTrayXLink *link, Preferences *pref, QObject *parent ) : QSystemTrayIcon( QIcon(), parent )
{
/*
* Initialize
*/
m_link = link;
m_pref = pref;
m_unread_mail = 0;
}
/*
* Set the icon type
*/
void SysTrayXIcon::setIconType( Preferences::IconType icon_type )
{
if( icon_type != m_icon_type )
{
/*
* Store the new value
*/
m_icon_type = icon_type;
/*
* Render and set a new icon in the tray
*/
renderIcon();
}
}
/*
* Set the icon mime
*/
void SysTrayXIcon::setIconMime( const QString& icon_mime )
{
if( m_icon_mime != icon_mime )
{
/*
* Store the new value
*/
m_icon_mime = icon_mime;
}
}
/*
* Set the icon type
*/
void SysTrayXIcon::setIconData( const QByteArray& icon_data )
{
if( m_icon_data != icon_data )
{
/*
* Store the new value
*/
m_icon_data = icon_data;
/*
* Render and set a new icon in the tray
*/
renderIcon();
}
}
/*
* Set the number of unread mails
*/
void SysTrayXIcon::setUnreadMail( int unread_mail )
{
if( unread_mail != m_unread_mail ) {
/*
* Store the new value
*/
m_unread_mail = unread_mail;
/*
* Render and set a new icon in the tray
*/
renderIcon();
}
}
/*
* Set and render the icon in the system tray
*/
void SysTrayXIcon::renderIcon()
{
QPixmap pixmap;
switch( m_icon_type )
{
case Preferences::PREF_BLANK_ICON:
case Preferences::PREF_NEWMAIL_ICON:
{
pixmap = QPixmap( ":/files/icons/blank-icon.png" );
break;
}
case Preferences::PREF_CUSTOM_ICON:
{
pixmap.loadFromData( m_icon_data );
break;
}
}
QString number = QString::number( m_unread_mail );
if( m_unread_mail > 0 )
{
/*
* Paint the number
*/
QPainter painter( &pixmap );
painter.setFont( QFont("Sans") );
double factor = pixmap.width() / ( 3 * painter.fontMetrics().width( number ) );
QFont font = painter.font();
font.setPointSizeF( font.pointSizeF() * factor );
font.setBold( true );
painter.setFont( font );
painter.drawText( pixmap.rect(), Qt::AlignCenter, QString::number( m_unread_mail ) );
}
/*
* Set the tray icon
*/
QSystemTrayIcon::setIcon( QIcon( pixmap ) );
}
/*
* Handle unread mail signal
*/
void SysTrayXIcon::slotSetUnreadMail( int unread_mail )
{
setUnreadMail( unread_mail );
}
/*
* Handle the icon type change signal
*/
void SysTrayXIcon::slotIconTypeChange()
{
setIconType( m_pref->getIconType() );
}
/*
* Handle the icon data change signal
*/
void SysTrayXIcon::slotIconDataChange()
{
setIconMime( m_pref->getIconMime() );
setIconData( m_pref->getIconData() );
}

View File

@@ -0,0 +1,132 @@
#ifndef SYSTRAYXICON_H
#define SYSTRAYXICON_H
/*
* Local includes
*/
#include "preferences.h"
/*
* Qt includes
*/
#include <QSystemTrayIcon>
/*
* Predefines
*/
class SysTrayXLink;
/**
* @brief The systrayxtray class. The system tray icon.
*/
class SysTrayXIcon : public QSystemTrayIcon
{
Q_OBJECT
public:
/**
* @brief SysTrayXIcon. Constructor.
*
* @param parent My parent.
*/
SysTrayXIcon( SysTrayXLink *link, Preferences *pref, QObject *parent = nullptr );
/**
* @brief setIconType. Set the sytem tray icon type.
*
* @param icon_type The icon type
*/
void setIconType( Preferences::IconType icon_type );
/**
* @brief setIconMime. Set the sytem tray icon mime.
*
* @param icon_mime The icon mime
*/
void setIconMime( const QString& icon_mime );
/**
* @brief setIconData. Set the custom icon data.
*
* @param icon_data The icon data.
*/
void setIconData( const QByteArray& icon_data );
/**
* @brief setUnreadMail. Set the number of unread mails.
*
* @param unread_mail The number of unread mails.
*/
void setUnreadMail( int unread_mail );
signals:
/**
* @brief signalDebugMessage. Signal a debug message.
*
* @param message The message.
*/
void signalDebugMessage( QString message );
public slots:
/**
* @brief slotSetUnreadMail. Slot for handling unread mail signals.
*
* @param unread_mail The number of unread mails.
*/
void slotSetUnreadMail( int unread_mail );
/**
* @brief slotIconTypeChange. Slot for handling icon type change signals.
*/
void slotIconTypeChange();
/**
* @brief slotIconDataChange. Slot for handling icon data change signals.
*/
void slotIconDataChange();
private:
/**
* @brief setIcon. Set a new rendered icon.
*/
void renderIcon();
private:
/**
* @brief m_link. Pointer to the link.
*/
SysTrayXLink *m_link;
/**
* @brief m_pref Pointer to the preferences storage.
*/
Preferences *m_pref;
/**
* @brief m_icon_type. Storage for the icon type.
*/
Preferences::IconType m_icon_type;
/**
* @brief m_icon_mime. Storage for the icon mime.
*/
QString m_icon_mime;
/**
* @brief m_icon_data. Storage for the icon.
*/
QByteArray m_icon_data;
/**
* @brief m_unread_mail. Storage for the number of unread mails.
*/
int m_unread_mail;
};
#endif // SYSTRAYXICON_H

View File

@@ -3,21 +3,34 @@
/*
* Local includes
*/
#include "preferences.h"
/*
* System includes
*/
#include <unistd.h>
/*
* Qt includes
*/
#include <QFile>
#include <QString>
#include <QVariant>
#include <QDataStream>
#include <QJsonObject>
#include <QJsonValue>
#include <QSocketNotifier>
/*
* Constructor
*/
SysTrayXLink::SysTrayXLink()
SysTrayXLink::SysTrayXLink( Preferences *pref )
{
/*
* Store preferences
*/
m_pref = pref;
/*
* Open stdin
*/
@@ -30,25 +43,20 @@ SysTrayXLink::SysTrayXLink()
m_stdout = new QFile( this );
m_stdout->open( stdout, QIODevice::WriteOnly );
/*
* Open dump.txt
*/
m_dump = new QFile( "dump.txt", this );
m_dump->open( QIODevice::WriteOnly );
/*
* Setup the notifiers
*/
m_notifierLinkRead = new QSocketNotifier( STDIN_FILENO, QSocketNotifier::Read, this );
connect( m_notifierLinkRead, &QSocketNotifier::activated, this, &SysTrayXLink::slotLinkRead );
m_notifierLinkReadException = new QSocketNotifier( STDIN_FILENO, QSocketNotifier::Exception, this );
connect( m_notifierLinkReadException, &QSocketNotifier::activated, this, &SysTrayXLink::slotLinkReadException );
QDataStream out( m_stdout );
char reply[] = "\"Hallo other World!\"";
qint32 replylen = sizeof( reply ) - 1;
out.writeRawData( reinterpret_cast< char* >( &replylen ), sizeof( qint32 ) );
out.writeRawData( reply, replylen );
m_notifier_link_read = new QSocketNotifier( STDIN_FILENO, QSocketNotifier::Read, this );
connect( m_notifier_link_read, &QSocketNotifier::activated, this, &SysTrayXLink::slotLinkRead );
m_notifier_link_read_exception = new QSocketNotifier( STDIN_FILENO, QSocketNotifier::Exception, this );
connect( m_notifier_link_read_exception, &QSocketNotifier::activated, this, &SysTrayXLink::slotLinkReadException );
}
@@ -66,8 +74,178 @@ SysTrayXLink::~SysTrayXLink()
m_stdout->close();
delete m_stdout;
delete m_notifierLinkRead;
delete m_notifierLinkReadException;
m_dump->close();
delete m_dump;
delete m_notifier_link_read;
delete m_notifier_link_read_exception;
}
/*
* Write a message to the link
*/
void SysTrayXLink::linkWrite( const QByteArray& message )
{
QDataStream out( m_stdout );
qint32 msglen = message.length();
int status1 = out.writeRawData( reinterpret_cast< char* >( &msglen ), sizeof( qint32 ) );
int status2 = out.writeRawData( message.data(), msglen );
m_stdout->flush();
if( status1 && status2 )
{
//error handling?
}
}
/*
* Send the preferences to the add-on
*/
void SysTrayXLink::sendPreferences()
{
/*
* Enacode the preferences into a JSON doc
*/
EncodePreferences( *m_pref );
QFile dump("/home/maxime/dumpJSON_app2addon.txt");
dump.open(QIODevice::WriteOnly );
dump.write( m_pref_json_doc.toJson( QJsonDocument::Compact ).data(), m_pref_json_doc.toJson( QJsonDocument::Compact ).length() );
dump.close();
/*
* Send them to the add-on
*/
linkWrite( m_pref_json_doc.toJson( QJsonDocument::Compact ) );
}
/*
* Decode JSON message
*/
void SysTrayXLink::DecodeMessage( const QByteArray& message )
{
QJsonParseError jsonError;
QJsonDocument jsonResponse = QJsonDocument::fromJson( message, &jsonError );
if( jsonError.error == QJsonParseError::NoError )
{
QJsonObject jsonObject = jsonResponse.object();
if( jsonObject.contains( "unreadMail" ) && jsonObject[ "unreadMail" ].isDouble() )
{
int unreadMail = jsonObject[ "unreadMail" ].toInt();
emit signalUnreadMail( unreadMail );
}
if( jsonObject.contains( "preferences" ) && jsonObject[ "preferences" ].isObject() )
{
QFile dump("/home/maxime/dumpJSON_addon2app.txt");
dump.open(QIODevice::WriteOnly );
dump.write( message.data(), message.length() );
dump.close();
DecodePreferences( jsonObject[ "preferences" ].toObject() );
}
}
else
{
emit signalLinkReceiveError( jsonError.errorString() );
}
}
/*
* Decode preferences from JSON message
*/
void SysTrayXLink::DecodePreferences( const QJsonObject& pref )
{
/*
* Check the received object
*/
if( pref.contains( "iconType" ) && pref[ "iconType" ].isString() )
{
Preferences::IconType icon_type = static_cast< Preferences::IconType >( pref[ "iconType" ].toString().toInt() );
/*
* Store the new icon type
*/
m_pref->setIconType( icon_type );
}
if( pref.contains( "iconMime" ) && pref[ "iconMime" ].isString() )
{
QString icon_mime = pref[ "iconMime" ].toString();
/*
* Store the new icon mime
*/
m_pref->setIconMime( icon_mime );
}
if( pref.contains( "icon" ) && pref[ "icon" ].isString() )
{
QString icon_base64 = pref[ "icon" ].toString();
/*
QFile dump("xxxxx");
dump.open(QIODevice::WriteOnly );
dump.write( icon_base64.toUtf8().data(), icon_base64.toUtf8().length() );
dump.close();
*/
/*
* Store the new icon data
*/
m_pref->setIconData( QByteArray::fromBase64( icon_base64.toUtf8() ) );
}
if( pref.contains( "debug" ) && pref[ "debug" ].isString() )
{
bool debug = pref[ "debug" ].toString() == "true";
/*
* Store the new debug state
*/
m_pref->setDebug( debug );
}
}
/*
* Encode preferences to JSON message
*/
void SysTrayXLink::EncodePreferences( const Preferences& pref )
{
/*
* Setup the preferences JSON
*/
QJsonObject prefObject;
prefObject.insert("debug", QJsonValue::fromVariant( QString( pref.getDebug() ? "true" : "false" ) ) );
prefObject.insert("iconType", QJsonValue::fromVariant( QString::number( pref.getIconType() ) ) );
prefObject.insert("iconMime", QJsonValue::fromVariant( pref.getIconMime() ) );
prefObject.insert("icon", QJsonValue::fromVariant( QString( pref.getIconData().toBase64() ) ) );
QJsonObject preferencesObject;
preferencesObject.insert("preferences", prefObject );
/*
* Store the new document
*/
m_pref_json_doc = QJsonDocument( preferencesObject );
}
@@ -81,38 +259,30 @@ void SysTrayXLink::slotLinkRead()
qint32 msglen;
int status1 = in.readRawData( reinterpret_cast< char* >( &msglen ), sizeof( qint32 ) );
emit signalReceivedMessageLength(msglen);
emit signalReceivedMessageLength( msglen );
QByteArray message(msglen + 1, 0 );
QByteArray message(msglen, 0 );
int status2 = in.readRawData( message.data(), msglen );
emit signalReceivedMessage( message );
m_dump->write( message );
/*
* Decode the message
*/
DecodeMessage( message );
if( ( status1 == 4 ) && ( status2 == msglen ) )
{
//dummy
//error handling?
}
/*
QDataStream out( m_stdout );
char reply[] = "\"Hallo other World!\"";
qint32 replylen = sizeof( reply ) - 1;
int status3 = out.writeRawData( reinterpret_cast< char* >( &replylen ), sizeof( qint32 ) );
int status4 = out.writeRawData( reply, replylen );
m_stdout->flush();
if( status3 && status4 )
{
//dummy
}
*/
}
/*
* Handle notifier exception
* Handle read notifier exception
*/
void SysTrayXLink::slotLinkReadException()
{
@@ -120,23 +290,46 @@ void SysTrayXLink::slotLinkReadException()
}
/*
* Read the input
* write the output
*/
void SysTrayXLink::slotLinkWrite( QByteArray message )
{
QDataStream out( m_stdout );
linkWrite( message );
}
qint32 msglen = message.length();
int status1 = out.writeRawData( reinterpret_cast< char* >( &msglen ), sizeof( qint32 ) );
int status2 = out.writeRawData( message.data(), msglen );
m_stdout->flush();
if( status1 && status2 )
/*
* Handle a debug state change signal
*/
void SysTrayXLink::slotDebugChange()
{
if( m_pref->getAppPrefChanged() )
{
//dummy
sendPreferences();
}
}
/*
* Handle the icon type change signal
*/
void SysTrayXLink::slotIconTypeChange()
{
if( m_pref->getAppPrefChanged() )
{
sendPreferences();
}
}
/*
* Handle the icon data change signal
*/
void SysTrayXLink::slotIconDataChange()
{
if( m_pref->getAppPrefChanged() )
{
sendPreferences();
}
}

View File

@@ -4,11 +4,13 @@
/*
* Local includes
*/
#include "preferences.h"
/*
* Qt includes
*/
#include <QObject>
#include <QJsonDocument>
/*
* Predefines
@@ -28,16 +30,66 @@ class SysTrayXLink : public QObject
/**
* @brief SysTrayXLink. Constructor, destructor.
*/
SysTrayXLink();
SysTrayXLink( Preferences *pref );
~SysTrayXLink();
/**
* @brief linkWrite. Write a message to the link.
*
* @param message Message to be written.
*/
void linkWrite( const QByteArray& message );
/**
* @brief sendPreferences. Send the preferences to the add-on.
*/
void sendPreferences();
private:
/**
* @brief MessageDecode. Decode a JSON message.
*
* @param message The message.
*/
void DecodeMessage( const QByteArray& message );
/**
* @brief DecodePreferences. Decode a JSON preference object.
*
* @param pref The JSON preferences.
*/
void DecodePreferences( const QJsonObject& pref );
/**
* @brief EncodePreferences. Encode the preferences into a JSON document.
*
* @param pref The preferences.
*/
void EncodePreferences( const Preferences& pref );
public slots:
/**
* @brief slotDebugChange. Handle a change in debug state.
*/
void slotDebugChange();
/**
* @brief slotLinkWrite. Write the link.
*/
void slotLinkWrite( QByteArray message );
/**
* @brief slotIconTypeChange. Slot for handling icon type change signals.
*/
void slotIconTypeChange();
/**
* @brief slotIconDataChange. Slot for handling icon data change signals.
*/
void slotIconDataChange();
private slots:
/**
@@ -57,17 +109,43 @@ class SysTrayXLink : public QObject
*
* @param msglen
*/
void signalReceivedMessageLength(qint32 msglen);
void signalReceivedMessageLength( qint32 msglen );
/**
* @brief signalReceivedMessage
*
* @param message
*/
void signalReceivedMessage(QByteArray message);
void signalReceivedMessage( QByteArray message );
/**
* @brief signalLinkReceiveError. Cannot parse received JSON message.
*
* @param error JSON error message
*/
void signalLinkReceiveError( QString error );
/**
* @brief signalDebugMessage. Signal a debug message.
*
* @param message The message.
*/
void signalDebugMessage( QString message );
/**
* @brief signalUnreadMail. Signal numder of unread mails.
*
* @param unreadMail The number of unread mails.
*/
void signalUnreadMail( int unread_mail );
private:
/**
* @brief m_pref. Pointer to the preferences storage.
*/
Preferences *m_pref;
/**
* @brief m_stdin. Pointer to stdin file.
*/
@@ -79,14 +157,24 @@ class SysTrayXLink : public QObject
QFile *m_stdout;
/**
* @brief m_notifierLinkRead. Pointers to the link read data notifier.
* @brief m_dump. Pointer to dump file.
*/
QSocketNotifier *m_notifierLinkRead;
QFile *m_dump;
/**
* @brief m_notifierLinkReadException. Pointers to the link read exception notifier.
* @brief m_notifier_link_read. Pointers to the link read data notifier.
*/
QSocketNotifier *m_notifierLinkReadException;
QSocketNotifier *m_notifier_link_read;
/**
* @brief m_notifier_link_read_exception. Pointers to the link read exception notifier.
*/
QSocketNotifier *m_notifier_link_read_exception;
/**
* @brief m_pref_json_doc. Temporary storage for the preferences to be send.
*/
QJsonDocument m_pref_json_doc;
};
#endif // SYSTRAYXLINK_H

View File

@@ -13,26 +13,62 @@ SysTrayX.Messaging = {
],
init: function() {
if (this.initialized) {
console.log("Messaging already initialized");
return;
}
console.log("Enabling Messaging");
// Get the accounts from the storage
SysTrayX.Messaging.getAccounts();
browser.storage.onChanged.addListener(SysTrayX.Messaging.storageChanged);
// Send preferences to app
SysTrayX.Messaging.sendPreferences();
// this.unReadMessages(this.unreadFiltersTest).then(this.unreadCb);
window.setInterval(SysTrayX.Messaging.pollAccounts, 1000);
window.setInterval(SysTrayX.Messaging.pollAccounts, 10000);
this.initialized = true;
},
//
// Handle a storage change
//
storageChanged: function(changes, area) {
console.debug("Changes in store");
// Get the new preferences
SysTrayX.Messaging.getAccounts();
if ("addonprefchanged" in changes && changes["addonprefchanged"].newValue) {
console.debug("Sending preference");
//
// Send new preferences to the app
//
SysTrayX.Messaging.sendPreferences();
// Reset flag
browser.storage.sync.set({
addonprefchanged: false
});
}
/*
var changedItems = Object.keys(changes);
for (var item of changedItems) {
console.log(item + " has changed:");
console.log("Old value: ");
console.log(changes[item].oldValue);
console.log("New value: ");
console.log(changes[item].newValue);
}
*/
},
//
// Poll the accounts
//
pollAccounts: function() {
console.debug("Polling");
SysTrayX.Messaging.getAccounts();
//
// Get the unread nessages of the selected accounts
//
@@ -40,9 +76,11 @@ SysTrayX.Messaging = {
let filtersAttr = filtersDiv.getAttribute("data-filters");
let filters = JSON.parse(filtersAttr);
if (filters.length > 0) {
SysTrayX.Messaging.unReadMessages(filters).then(
SysTrayX.Messaging.unreadCb
);
}
},
//
@@ -71,7 +109,67 @@ SysTrayX.Messaging = {
// Callback for unReadMessages
//
unreadCb: function(count) {
console.log("SysTrayX unread " + count);
SysTrayX.Link.postSysTrayXMessage({ unreadMail: count });
},
sendPreferences: function() {
console.debug("Send preferences");
let getter = browser.storage.sync.get([
"debug",
"iconType",
"iconMime",
"icon"
]);
getter.then(this.sendPreferencesStorage, this.onSendPreferecesStorageError);
},
sendPreferencesStorage: function(result) {
console.debug("Get preferences from storage");
let debug = result.debug || "false";
let iconType = result.iconType || "0";
let iconMime = result.iconMime || "image/png";
let icon = result.icon || [];
console.log("Debug" + debug);
console.log("Type" + iconType);
console.log("Mime" + iconMime);
console.log(icon);
// Send it to the app
SysTrayX.Link.postSysTrayXMessage({
preferences: {
debug: debug,
iconType: iconType,
iconMime: iconMime,
icon: icon
}
});
},
onSendIconStorageError: function(error) {
console.log(`GetIcon Error: ${error}`);
},
//
// Get the accounts from the storage
//
getAccounts: function() {
console.debug("Get accounts");
let getter = browser.storage.sync.get(["accounts", "filters"]);
getter.then(this.getAccountsStorage, this.onGetAccountsStorageError);
if (SysTrayX.debugAccounts) {
let accountsDiv = document.getElementById("accounts");
let accountsAttr = accountsDiv.getAttribute("data-accounts");
console.debug("Accounts attr: " + accountsAttr);
let accounts = JSON.parse(accountsAttr);
console.debug("Accounts poll: " + accounts.length);
}
},
//
@@ -96,28 +194,11 @@ SysTrayX.Messaging = {
onGetAccountsStorageError: function(error) {
console.log(`GetAccounts Error: ${error}`);
},
getAccounts: function() {
console.debug("Get accounts");
let getter = browser.storage.sync.get(["accounts", "filters"]);
getter.then(this.getAccountsStorage, this.onGetAccountsStorageError);
if (SysTrayX.debugAccounts) {
let accountsDiv = document.getElementById("accounts");
let accountsAttr = accountsDiv.getAttribute("data-accounts");
console.debug("Accounts attr: " + accountsAttr);
let accounts = JSON.parse(accountsAttr);
console.debug("Accounts poll: " + accounts.length);
}
}
};
//
// Link object, handles the native messaging to the system tray app
// Link object. Handles the native messaging to the system tray app
//
SysTrayX.Link = {
portSysTrayX: undefined,
@@ -130,25 +211,57 @@ SysTrayX.Link = {
this.portSysTrayX.onMessage.addListener(
SysTrayX.Link.receiveSysTrayXMessage
);
// Setup test loop
window.setInterval(SysTrayX.Link.postSysTrayXMessage, 1000);
},
postSysTrayXMessage: function() {
console.log("Sending: Hallo World!");
SysTrayX.Link.portSysTrayX.postMessage("Hallo World!");
// SysTrayX.Link.portSysTrayX.postMessage({ key: "Hallo", value: "World!" });
postSysTrayXMessage: function(object) {
// Send object (will be stringified by postMessage)
SysTrayX.Link.portSysTrayX.postMessage(object);
},
receiveSysTrayXMessage: function(response) {
console.log("Received: " + response);
if (response["preferences"]) {
// Store the preferences from the app
console.log("Preferences received");
let iconMime = response["preferences"].iconMime;
if (iconMime) {
browser.storage.sync.set({
iconMime: iconMime
});
}
let icon = response["preferences"].icon;
if (icon) {
browser.storage.sync.set({
icon: icon
});
}
let iconType = response["preferences"].iconType;
if (iconType) {
browser.storage.sync.set({
iconType: iconType
});
}
let debug = response["preferences"].debug;
if (debug) {
browser.storage.sync.set({
debug: debug
});
}
}
}
};
console.log("Starting SysTray-X");
SysTrayX.Messaging.init();
// Setup the link first
SysTrayX.Link.init();
// Main start
SysTrayX.Messaging.init();
console.log("Done");

View File

@@ -100,3 +100,11 @@ ul,
.active {
display: block;
}
.custom-icon-container {
display: flex;
}
.custom-icon-container > div {
margin: 10px;
}

View File

@@ -4,15 +4,7 @@ SysTrayX.Accounts = {
initialized: false,
init: function() {
if (this.initialized) {
console.log("Accounts already initialized");
return;
}
console.log("Enabling Accounts");
this.getAccounts().then(this.getAccountsCb);
this.initialized = true;
},
/*

View File

@@ -0,0 +1,36 @@
function fileSelected() {
let input = document.getElementById("selectedFileIconType");
if (input.files.length > 0) {
console.debug("Selected file: " + input.files[0].name);
console.debug("Selected file type: " + input.files[0].type);
}
function storeFile() {
let buffer = new Uint8Array(fr.result);
let binary = "";
let len = buffer.byteLength;
for (let i = 0; i < len; i++) {
binary += String.fromCharCode(buffer[i]);
}
let base64 = window.btoa(binary);
let iconDiv = document.getElementById("icon");
iconDiv.setAttribute("data-icon", base64);
iconDiv.setAttribute("data-icon-mime", input.files[0].type);
let image = document.getElementById("customIconImage");
image.setAttribute("src", `data:${input.files[0].type};base64,${base64}` );
console.log(base64);
}
fr = new FileReader();
fr.onload = storeFile;
fr.readAsArrayBuffer(input.files[0]);
}
document
.getElementById("selectedFileIconType")
.addEventListener("change", fileSelected);

View File

@@ -10,6 +10,12 @@
<script src="js/options_accounts.js"></script>
<br />
<div id="debugselect">
<input type="checkbox" name="debug" value="Debug" /> Display debug window<br/>
</div>
<br />
<div class="tab">
<button class="tablinks active" id="Windows">__MSG_tabWindows__</button>
<button class="tablinks" id="Icon">__MSG_tabIcon__</button>
@@ -21,7 +27,7 @@
<h3>Windows</h3>
<p>Windows options here</p>
<p>Please select your opton:</p>
<p>Please select your option:</p>
<input type="radio" name="options_test" value="Option1" /> Option 1<br />
<input type="radio" name="options_test" value="Option2" /> Option 2<br />
<input type="radio" name="options_test" value="Option3" /> Option 3<br />
@@ -30,22 +36,46 @@
<input type="checkbox" name="check1" value="Check1" /> Check 1<br />
<input type="checkbox" name="check2" value="Check2" /> Check 2<br />
<input type="checkbox" name="check3" value="Check3" /> Check 3<br />
</form>
</div>
<div id="IconContent" class="tabcontent">
<form>
<form name="iconform">
<h3>Icon</h3>
<p>Icon options here.</p>
<p>Please select your option:</p>
<table id="iconselect">
<tr>
<td><input type="radio" name="iconType" value="0" /> Blank icon</td>
</tr>
<tr>
<td><input type="radio" name="iconType" value="1" /> New mail icon</td>
</tr>
<tr>
<td><input type="radio" name="iconType" value="2" /> Custom icon</td>
<td><img id="customIconImage" height="25" width="25" align="middle" src=""></td>
<td>
<label for="selectedFileIconType" style="-moz-appearance: button;"}>Browse...</label>
<input type="file" id="selectedFileIconType" accept="image/*" style="display:none;">
</td>
</tr>
</table>
</form>
<div id="icon" data-icon-mime="" data-icon=""></div>
<script src="js/options_iconform.js"></script>
</div>
<div id="MailContent" class="tabcontent">
<form>
<form name="mailform">
<h3>Included accounts</h3>
<ul id="accountsTree"></ul>
</form>
</form name="mailform">
</div>
<br />
<form name="saveform">

View File

@@ -1,4 +1,7 @@
function saveOptions(e) {
var SysTrayX = {};
SysTrayX.SaveOptions = {
start: function(e) {
e.preventDefault();
console.debug("Save preferences");
@@ -12,9 +15,9 @@ function saveOptions(e) {
optionsCheck3: document.querySelector('input[name="check3"]').checked
});
/*
* Save accounts and filters
*/
//
// Save accounts and filters
//
console.debug("Store accounts and filters");
@@ -53,42 +56,247 @@ function saveOptions(e) {
});
console.debug("Store accounts and filters done");
}
function restoreOptions() {
//
// Save debug state
//
let debug = document.querySelector('input[name="debug"]').checked;
browser.storage.sync.set({
debug: `${debug}`
});
console.debug("Store debug state: " + `${debug}`);
//
// Save icon preferences
//
console.debug("Store icon preferences");
let iconType = document.querySelector('input[name="iconType"]:checked')
.value;
// Store icon type
browser.storage.sync.set({
iconType: iconType
});
let iconDiv = document.getElementById("icon");
let iconBase64 = iconDiv.getAttribute("data-icon");
let iconMime = iconDiv.getAttribute("data-icon-mime");
// Store icon (base64)
browser.storage.sync.set({
iconMime: iconMime,
icon: iconBase64
});
console.debug("Store icon preferences done");
// Mark add-on preferences changed
browser.storage.sync.set({
addonprefchanged: true
});
}
};
SysTrayX.RestoreOptions = {
start: function() {
console.debug("Restore preferences");
function setCurrentRadioChoice(result) {
//
// Test 1
//
let getting = browser.storage.sync.get("optionsRadioTest");
getting.then(
SysTrayX.RestoreOptions.setCurrentRadioChoice,
SysTrayX.RestoreOptions.onError
);
//
// Test 2
//
getting = browser.storage.sync.get([
"optionsCheck1",
"optionsCheck2",
"optionsCheck3"
]);
getting.then(
SysTrayX.RestoreOptions.setCurrentCheckChoice,
SysTrayX.RestoreOptions.onError
);
console.debug("Restore icon preferences");
//
// Restore debug state
//
let getDebug = browser.storage.sync.get("debug");
getDebug.then(
SysTrayX.RestoreOptions.setDebug,
SysTrayX.RestoreOptions.onDebugError
);
//
// Restore icon type
//
let getIconType = browser.storage.sync.get("iconType");
getIconType.then(
SysTrayX.RestoreOptions.setIconType,
SysTrayX.RestoreOptions.onIconTypeError
);
//
// Restore icon
//
let getIcon = browser.storage.sync.get(["iconMime", "icon"]);
getIcon.then(
SysTrayX.RestoreOptions.setIcon,
SysTrayX.RestoreOptions.onIconError
);
console.debug("Restore icon preferences done");
},
//
// Test 1 Callback
//
setCurrentRadioChoice: function(result) {
let selector = result.optionsRadioTest || "Option1";
let radioButton = document.querySelector(`[value=${selector}]`);
radioButton.checked = true;
}
},
function setCurrentCheckChoice(result) {
//
// Test 2 Callback
//
setCurrentCheckChoice: function(result) {
let checkbox1 = document.querySelector('[name="check1"]');
checkbox1.checked = result.optionsCheck1 || false;
let checkbox2 = document.querySelector('[name="check2"]');
checkbox2.checked = result.optionsCheck2 || false;
let checkbox3 = document.querySelector('[name="check3"]');
checkbox3.checked = result.optionsCheck3 || false;
}
},
function onError(error) {
//
// Test 1+2 error callback
//
onError: function(error) {
console.log(`Error: ${error}`);
},
//
// Restore debug state callbacks
//
setDebug: function(result) {
let debug = result.debug || "false";
console.debug("Debug: " + debug);
let checkbox = document.querySelector(`input[name="debug"]`);
checkbox.checked = (debug === "true");
},
onDebugError: function(error) {
console.log(`Debug Error: ${error}`);
},
//
// Restore icon type callbacks
//
setIconType: function(result) {
let iconType = result.iconType || "0";
let radioButton = document.querySelector(`[value="${iconType}"]`);
radioButton.checked = true;
},
onIconTypeError: function(error) {
console.log(`Icon type Error: ${error}`);
},
//
// Restore icon
//
setIconMime: function(result) {
let iconMime = result.iconMime || "image/png";
let iconDiv = document.getElementById("icon");
iconDiv.setAttribute("data-icon-mime", iconMime);
},
setIconData: function(result) {
let iconBase64 = result.icon || "";
let iconDiv = document.getElementById("icon");
iconDiv.setAttribute("data-icon", iconBase64);
},
updateIconImage: function() {
let iconDiv = document.getElementById("icon");
icon_mime = iconDiv.getAttribute("data-icon-mime");
icon_data = iconDiv.getAttribute("data-icon");
let image = document.getElementById("customIconImage");
image.setAttribute("src", `data:${icon_mime};base64,${icon_data}`);
},
setIcon: function(result) {
SysTrayX.RestoreOptions.setIconMime(result);
SysTrayX.RestoreOptions.setIconData(result);
SysTrayX.RestoreOptions.updateIconImage();
},
onIconError: function(error) {
console.log(`Icon Error: ${error}`);
}
};
SysTrayX.StorageChanged = {
changed: function(changes, area) {
// Try to keep the preferences of the add-on and the app in sync
let changedItems = Object.keys(changes);
let changed_icon = false;
let changed_icon_mime = false;
for (let item of changedItems) {
if (item === "iconMime") {
SysTrayX.RestoreOptions.setIconMime({
iconMime: changes[item].newValue
});
}
if (item === "icon") {
SysTrayX.RestoreOptions.setIcon({ icon: changes[item].newValue });
changed_icon = true;
}
if (item === "iconType") {
SysTrayX.RestoreOptions.setIconType({
iconType: changes[item].newValue
});
changed_icon_mime = true;
}
if (item === "debug") {
SysTrayX.RestoreOptions.setDebug({
debug: changes[item].newValue
});
}
}
var getting = browser.storage.sync.get("optionsRadioTest");
getting.then(setCurrentRadioChoice, onError);
if (changed_icon_mime && changed_icon) {
SysTrayX.RestoreOptions.updateIconImage();
}
var getting = browser.storage.sync.get([
"optionsCheck1",
"optionsCheck2",
"optionsCheck3"
]);
getting.then(setCurrentCheckChoice, onError);
}
//
// Update element
//
document.getElementById("debugselect").className = "active";
document.getElementById("iconselect").className = "active";
}
};
document.addEventListener("DOMContentLoaded", restoreOptions);
document.addEventListener("DOMContentLoaded", SysTrayX.RestoreOptions.start);
document
.querySelector('[name="saveform"]')
.addEventListener("submit", saveOptions);
.addEventListener("submit", SysTrayX.SaveOptions.start);
browser.storage.onChanged.addListener(SysTrayX.StorageChanged.changed);