in progress

This commit is contained in:
MSN 2013-11-23 10:48:34 +04:00
commit 6cd510e389
14 changed files with 749 additions and 0 deletions

244
GlobalActionHelper.cpp Normal file
View File

@ -0,0 +1,244 @@
#include "GlobalActionHelper.h"
#include <qt_windows.h>
#include <QDebug>
#include <QApplication>
QHash<QPair<quint32, quint32>, QAction*> GlobalActionHelper::actions_;
bool GlobalActionHelper::nativeEventFilter(const QByteArray& eventType,
void* message, long* result)
{
Q_UNUSED (eventType);
Q_UNUSED (result);
MSG* msg = static_cast<MSG*>(message);
if (msg->message == WM_HOTKEY)
{
const quint32 keycode = HIWORD(msg->lParam);
const quint32 modifiers = LOWORD(msg->lParam);
QAction* action = actions_.value (qMakePair (keycode, modifiers));
Q_CHECK_PTR (action);
action->activate (QAction::Trigger);
}
return false;
}
void GlobalActionHelper::init()
{
qApp->installNativeEventFilter (new GlobalActionHelper);
}
bool GlobalActionHelper::makeGlobal(QAction* action)
{
QKeySequence hotKey = action->shortcut ();
Qt::KeyboardModifiers allMods = Qt::ShiftModifier | Qt::ControlModifier |
Qt::AltModifier | Qt::MetaModifier;
Qt::Key key = hotKey.isEmpty() ?
Qt::Key(0) :
Qt::Key((hotKey[0] ^ allMods) & hotKey[0]);
Qt::KeyboardModifiers mods = hotKey.isEmpty() ?
Qt::KeyboardModifiers(0) :
Qt::KeyboardModifiers(hotKey[0] & allMods);
const quint32 nativeKey = nativeKeycode(key);
const quint32 nativeMods = nativeModifiers(mods);
const bool res = registerHotKey(nativeKey, nativeMods);
if (res)
actions_.insert (qMakePair(nativeKey, nativeMods), action);
else
qWarning() << "Failed to register global hotkey:" << hotKey.toString();
return res;
}
quint32 GlobalActionHelper::nativeKeycode(Qt::Key key)
{
switch (key)
{
case Qt::Key_Escape:
return VK_ESCAPE;
case Qt::Key_Tab:
case Qt::Key_Backtab:
return VK_TAB;
case Qt::Key_Backspace:
return VK_BACK;
case Qt::Key_Return:
case Qt::Key_Enter:
return VK_RETURN;
case Qt::Key_Insert:
return VK_INSERT;
case Qt::Key_Delete:
return VK_DELETE;
case Qt::Key_Pause:
return VK_PAUSE;
case Qt::Key_Print:
return VK_PRINT;
case Qt::Key_Clear:
return VK_CLEAR;
case Qt::Key_Home:
return VK_HOME;
case Qt::Key_End:
return VK_END;
case Qt::Key_Left:
return VK_LEFT;
case Qt::Key_Up:
return VK_UP;
case Qt::Key_Right:
return VK_RIGHT;
case Qt::Key_Down:
return VK_DOWN;
case Qt::Key_PageUp:
return VK_PRIOR;
case Qt::Key_PageDown:
return VK_NEXT;
case Qt::Key_F1:
return VK_F1;
case Qt::Key_F2:
return VK_F2;
case Qt::Key_F3:
return VK_F3;
case Qt::Key_F4:
return VK_F4;
case Qt::Key_F5:
return VK_F5;
case Qt::Key_F6:
return VK_F6;
case Qt::Key_F7:
return VK_F7;
case Qt::Key_F8:
return VK_F8;
case Qt::Key_F9:
return VK_F9;
case Qt::Key_F10:
return VK_F10;
case Qt::Key_F11:
return VK_F11;
case Qt::Key_F12:
return VK_F12;
case Qt::Key_F13:
return VK_F13;
case Qt::Key_F14:
return VK_F14;
case Qt::Key_F15:
return VK_F15;
case Qt::Key_F16:
return VK_F16;
case Qt::Key_F17:
return VK_F17;
case Qt::Key_F18:
return VK_F18;
case Qt::Key_F19:
return VK_F19;
case Qt::Key_F20:
return VK_F20;
case Qt::Key_F21:
return VK_F21;
case Qt::Key_F22:
return VK_F22;
case Qt::Key_F23:
return VK_F23;
case Qt::Key_F24:
return VK_F24;
case Qt::Key_Space:
return VK_SPACE;
case Qt::Key_Asterisk:
return VK_MULTIPLY;
case Qt::Key_Plus:
return VK_ADD;
case Qt::Key_Comma:
return VK_SEPARATOR;
case Qt::Key_Minus:
return VK_SUBTRACT;
case Qt::Key_Slash:
return VK_DIVIDE;
case Qt::Key_MediaNext:
return VK_MEDIA_NEXT_TRACK;
case Qt::Key_MediaPrevious:
return VK_MEDIA_PREV_TRACK;
case Qt::Key_MediaPlay:
return VK_MEDIA_PLAY_PAUSE;
case Qt::Key_MediaStop:
return VK_MEDIA_STOP;
// couldn't find those in VK_*
//case Qt::Key_MediaLast:
//case Qt::Key_MediaRecord:
case Qt::Key_VolumeDown:
return VK_VOLUME_DOWN;
case Qt::Key_VolumeUp:
return VK_VOLUME_UP;
case Qt::Key_VolumeMute:
return VK_VOLUME_MUTE;
// numbers
case Qt::Key_0:
case Qt::Key_1:
case Qt::Key_2:
case Qt::Key_3:
case Qt::Key_4:
case Qt::Key_5:
case Qt::Key_6:
case Qt::Key_7:
case Qt::Key_8:
case Qt::Key_9:
return key;
// letters
case Qt::Key_A:
case Qt::Key_B:
case Qt::Key_C:
case Qt::Key_D:
case Qt::Key_E:
case Qt::Key_F:
case Qt::Key_G:
case Qt::Key_H:
case Qt::Key_I:
case Qt::Key_J:
case Qt::Key_K:
case Qt::Key_L:
case Qt::Key_M:
case Qt::Key_N:
case Qt::Key_O:
case Qt::Key_P:
case Qt::Key_Q:
case Qt::Key_R:
case Qt::Key_S:
case Qt::Key_T:
case Qt::Key_U:
case Qt::Key_V:
case Qt::Key_W:
case Qt::Key_X:
case Qt::Key_Y:
case Qt::Key_Z:
return key;
default:
return 0;
}
}
quint32 GlobalActionHelper::nativeModifiers(Qt::KeyboardModifiers modifiers)
{
// MOD_ALT, MOD_CONTROL, (MOD_KEYUP), MOD_SHIFT, MOD_WIN
quint32 native = 0;
if (modifiers & Qt::ShiftModifier)
native |= MOD_SHIFT;
if (modifiers & Qt::ControlModifier)
native |= MOD_CONTROL;
if (modifiers & Qt::AltModifier)
native |= MOD_ALT;
if (modifiers & Qt::MetaModifier)
native |= MOD_WIN;
// TODO: resolve these?
//if (modifiers & Qt::KeypadModifier)
//if (modifiers & Qt::GroupSwitchModifier)
return native;
}
bool GlobalActionHelper::registerHotKey(quint32 nativeKey, quint32 nativeMods)
{
return RegisterHotKey(0, nativeMods ^ nativeKey, nativeMods, nativeKey);
}
bool GlobalActionHelper::unregisterHotKey(quint32 nativeKey, quint32 nativeMods)
{
return UnregisterHotKey(0, nativeMods ^ nativeKey);
}

28
GlobalActionHelper.h Normal file
View File

@ -0,0 +1,28 @@
#ifndef GLOBALACTIONHELPER_H
#define GLOBALACTIONHELPER_H
// Some functions copied from QXT lib
#include <QAbstractNativeEventFilter>
#include <QAction>
class GlobalActionHelper : public QAbstractNativeEventFilter
{
public:
bool nativeEventFilter (const QByteArray &eventType, void *message,
long *result);
static void init ();
static bool makeGlobal (QAction* action);
private:
static QHash<QPair<quint32, quint32>, QAction*> actions_;
static quint32 nativeKeycode (Qt::Key key);
static quint32 nativeModifiers (Qt::KeyboardModifiers modifiers);
static bool registerHotKey (quint32 nativeKey, quint32 nativeMods);
static bool unregisterHotKey (quint32 nativeKey, quint32 nativeMods);
};
#endif // GLOBALACTIONHELPER_H

73
Manager.cpp Normal file
View File

@ -0,0 +1,73 @@
#include "Manager.h"
#include <QDebug>
#include <QSystemTrayIcon>
#include <QMenu>
#include <QApplication>
#include <QDesktopWidget>
#include <QScreen>
#include "SettingsEditor.h"
#include "SelectionDialog.h"
#include "GlobalActionHelper.h"
Manager::Manager(QObject *parent) :
QObject(parent),
trayIcon_ (new QSystemTrayIcon (QIcon (":/images/icon.png"), this)),
selection_ (new SelectionDialog)
{
trayIcon_->show ();
trayIcon_->setContextMenu (trayContextMenu ());
selection_->setWindowIcon (trayIcon_->icon ());
connect (this, SIGNAL (showPixmap (QPixmap)),
selection_, SLOT (setPixmap (QPixmap)));
connect (selection_, SIGNAL (selected (QPixmap)),
SLOT (processRegion (QPixmap)));
GlobalActionHelper::init ();
}
Manager::~Manager()
{
}
QMenu*Manager::trayContextMenu()
{
QMenu* menu = new QMenu ();
QAction* capture = menu->addAction (tr ("Захват"), this, SLOT (capture ()),
tr ("Ctrl+Alt+Z"));
GlobalActionHelper::makeGlobal (capture);
menu->addAction (tr ("Настройки"), this, SLOT (settings ()));
menu->addAction (tr ("Выход"), this, SLOT (close ()));
return menu;
}
void Manager::capture()
{
QList<QScreen*> screens = QApplication::screens ();
Q_ASSERT (!screens.isEmpty ());
QScreen* screen = screens.first ();
Q_CHECK_PTR (screen);
WId desktopId = QApplication::desktop ()->winId ();
QPixmap pixmap = screen->grabWindow (desktopId);
Q_ASSERT (!pixmap.isNull ());
emit showPixmap (pixmap);
}
void Manager::settings()
{
SettingsEditor editor;
editor.setWindowIcon (trayIcon_->icon ());
editor.exec ();
}
void Manager::close()
{
QApplication::quit ();
}
void Manager::processRegion(QPixmap selected)
{
}

38
Manager.h Normal file
View File

@ -0,0 +1,38 @@
#ifndef MANAGER_H
#define MANAGER_H
#include <QObject>
#include <QPixmap>
class QMenu;
class QSystemTrayIcon;
class SelectionDialog;
class Manager : public QObject
{
Q_OBJECT
public:
explicit Manager(QObject *parent = 0);
~Manager ();
signals:
void showPixmap (QPixmap pixmap);
private slots:
void capture ();
void settings ();
void close ();
void processRegion (QPixmap selected);
private:
QMenu* trayContextMenu ();
private:
QSystemTrayIcon* trayIcon_;
SelectionDialog* selection_;
};
#endif // MANAGER_H

5
Recources.qrc Normal file
View File

@ -0,0 +1,5 @@
<RCC>
<qresource prefix="/images">
<file alias="icon.png">images/icon.png</file>
</qresource>
</RCC>

32
ScreenTranslator.pro Normal file
View File

@ -0,0 +1,32 @@
#-------------------------------------------------
#
# Project created by QtCreator 2013-11-22T12:00:23
#
#-------------------------------------------------
QT += core gui
greaterThan(QT_MAJOR_VERSION, 4): QT += widgets
TARGET = ScreenTranslator
TEMPLATE = app
SOURCES += main.cpp\
Manager.cpp \
SettingsEditor.cpp \
SelectionDialog.cpp \
GlobalActionHelper.cpp
HEADERS += \
Manager.h \
SettingsEditor.h \
SelectionDialog.h \
GlobalActionHelper.h
FORMS += \
SettingsEditor.ui \
SelectionDialog.ui
RESOURCES += \
Recources.qrc

88
SelectionDialog.cpp Normal file
View File

@ -0,0 +1,88 @@
#include "SelectionDialog.h"
#include "ui_SelectionDialog.h"
#include <QMouseEvent>
#include <QPainter>
#include <QDebug>
SelectionDialog::SelectionDialog(QWidget *parent) :
QDialog(parent),
ui(new Ui::SelectionDialog)
{
ui->setupUi(this);
setWindowFlags (Qt::FramelessWindowHint | Qt::NoDropShadowWindowHint |
Qt::WindowStaysOnTopHint);
ui->label->setAutoFillBackground(false);
ui->label->installEventFilter (this);
}
SelectionDialog::~SelectionDialog()
{
delete ui;
}
bool SelectionDialog::eventFilter(QObject* object, QEvent* event)
{
if (object != ui->label)
{
return QDialog::eventFilter (object, event);
}
if (event->type () == QEvent::MouseButtonPress)
{
QMouseEvent* mouseEvent = static_cast <QMouseEvent*> (event);
if (mouseEvent->button () == Qt::LeftButton)
{
startSelectPos_ = mouseEvent->pos ();
}
}
else if (event->type () == QEvent::MouseButtonRelease)
{
QMouseEvent* mouseEvent = static_cast <QMouseEvent*> (event);
if (mouseEvent->button () == Qt::LeftButton)
{
if (startSelectPos_.isNull () || currentPixmap_.isNull ())
{
QDialog::eventFilter (object, event);
}
QPoint endPos = mouseEvent->pos ();
QRect selection = QRect (startSelectPos_, endPos).normalized ();
startSelectPos_ = currentSelectPos_ = QPoint ();
QPixmap selectedPixmap = currentPixmap_.copy (selection);
emit selected (selectedPixmap);
// accept (); //DEBUG
}
}
else if (event->type () == QEvent::MouseMove)
{
QMouseEvent* mouseEvent = static_cast <QMouseEvent*> (event);
if (mouseEvent->buttons () & Qt::LeftButton)
{
currentSelectPos_ = mouseEvent->pos ();
ui->label->repaint ();
}
}
else if (event->type () == QEvent::Paint)
{
QPainter painter (ui->label);
painter.setPen (Qt::red);
QRect selection = QRect (startSelectPos_, currentSelectPos_).normalized ();
painter.drawRect (selection);
}
return QDialog::eventFilter (object, event);
}
void SelectionDialog::setPixmap(QPixmap pixmap)
{
Q_ASSERT (!pixmap.isNull ());
currentPixmap_ = pixmap;
QPalette palette = this->palette ();
palette.setBrush (this->backgroundRole (), pixmap);
this->setPalette (palette);
this->resize (pixmap.size ());
show ();
setFocus ();
}

34
SelectionDialog.h Normal file
View File

@ -0,0 +1,34 @@
#ifndef SELECTIONDIALOG_H
#define SELECTIONDIALOG_H
#include <QDialog>
#include <QPixmap>
namespace Ui {
class SelectionDialog;
}
class SelectionDialog : public QDialog
{
Q_OBJECT
public:
explicit SelectionDialog(QWidget *parent = 0);
~SelectionDialog();
bool eventFilter (QObject *object, QEvent *event);
signals:
void selected (QPixmap pixmap);
public slots:
void setPixmap (QPixmap pixmap);
private:
Ui::SelectionDialog *ui;
QPoint startSelectPos_;
QPoint currentSelectPos_;
QPixmap currentPixmap_;
};
#endif // SELECTIONDIALOG_H

31
SelectionDialog.ui Normal file
View File

@ -0,0 +1,31 @@
<?xml version="1.0" encoding="UTF-8"?>
<ui version="4.0">
<class>SelectionDialog</class>
<widget class="QDialog" name="SelectionDialog">
<property name="geometry">
<rect>
<x>0</x>
<y>0</y>
<width>400</width>
<height>300</height>
</rect>
</property>
<property name="windowTitle">
<string>Dialog</string>
</property>
<layout class="QGridLayout" name="gridLayout">
<property name="margin">
<number>0</number>
</property>
<item row="0" column="0">
<widget class="QLabel" name="label">
<property name="text">
<string/>
</property>
</widget>
</item>
</layout>
</widget>
<resources/>
<connections/>
</ui>

14
SettingsEditor.cpp Normal file
View File

@ -0,0 +1,14 @@
#include "SettingsEditor.h"
#include "ui_SettingsEditor.h"
SettingsEditor::SettingsEditor(QWidget *parent) :
QDialog(parent),
ui(new Ui::SettingsEditor)
{
ui->setupUi(this);
}
SettingsEditor::~SettingsEditor()
{
delete ui;
}

22
SettingsEditor.h Normal file
View File

@ -0,0 +1,22 @@
#ifndef SETTINGSEDITOR_H
#define SETTINGSEDITOR_H
#include <QDialog>
namespace Ui {
class SettingsEditor;
}
class SettingsEditor : public QDialog
{
Q_OBJECT
public:
explicit SettingsEditor(QWidget *parent = 0);
~SettingsEditor();
private:
Ui::SettingsEditor *ui;
};
#endif // SETTINGSEDITOR_H

127
SettingsEditor.ui Normal file
View File

@ -0,0 +1,127 @@
<?xml version="1.0" encoding="UTF-8"?>
<ui version="4.0">
<class>SettingsEditor</class>
<widget class="QDialog" name="SettingsEditor">
<property name="geometry">
<rect>
<x>0</x>
<y>0</y>
<width>400</width>
<height>300</height>
</rect>
</property>
<property name="windowTitle">
<string>Dialog</string>
</property>
<widget class="QDialogButtonBox" name="buttonBox">
<property name="geometry">
<rect>
<x>30</x>
<y>240</y>
<width>341</width>
<height>32</height>
</rect>
</property>
<property name="orientation">
<enum>Qt::Horizontal</enum>
</property>
<property name="standardButtons">
<set>QDialogButtonBox::Cancel|QDialogButtonBox::Ok</set>
</property>
</widget>
<widget class="QLabel" name="label">
<property name="geometry">
<rect>
<x>50</x>
<y>40</y>
<width>46</width>
<height>13</height>
</rect>
</property>
<property name="text">
<string>TextLabel</string>
</property>
</widget>
<widget class="QLabel" name="label_2">
<property name="geometry">
<rect>
<x>40</x>
<y>80</y>
<width>46</width>
<height>13</height>
</rect>
</property>
<property name="text">
<string>TextLabel</string>
</property>
</widget>
<widget class="QLabel" name="label_3">
<property name="geometry">
<rect>
<x>50</x>
<y>120</y>
<width>46</width>
<height>13</height>
</rect>
</property>
<property name="text">
<string>One time select</string>
</property>
</widget>
<widget class="QComboBox" name="comboBox">
<property name="geometry">
<rect>
<x>160</x>
<y>80</y>
<width>69</width>
<height>22</height>
</rect>
</property>
</widget>
<widget class="QComboBox" name="comboBox_2">
<property name="geometry">
<rect>
<x>160</x>
<y>40</y>
<width>69</width>
<height>22</height>
</rect>
</property>
</widget>
</widget>
<resources/>
<connections>
<connection>
<sender>buttonBox</sender>
<signal>accepted()</signal>
<receiver>SettingsEditor</receiver>
<slot>accept()</slot>
<hints>
<hint type="sourcelabel">
<x>248</x>
<y>254</y>
</hint>
<hint type="destinationlabel">
<x>157</x>
<y>274</y>
</hint>
</hints>
</connection>
<connection>
<sender>buttonBox</sender>
<signal>rejected()</signal>
<receiver>SettingsEditor</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>
</ui>

BIN
images/icon.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 6.5 KiB

13
main.cpp Normal file
View File

@ -0,0 +1,13 @@
#include <QApplication>
#include <Manager.h>
int main(int argc, char *argv[])
{
QApplication a(argc, argv);
// a.setQuitOnLastWindowClosed (false);//DEBUG
Manager manager;
return a.exec();
}