From 6cd510e389a482934ed29a60a55737da1b0efc40 Mon Sep 17 00:00:00 2001 From: MSN Date: Sat, 23 Nov 2013 10:48:34 +0400 Subject: [PATCH] in progress --- GlobalActionHelper.cpp | 244 +++++++++++++++++++++++++++++++++++++++++ GlobalActionHelper.h | 28 +++++ Manager.cpp | 73 ++++++++++++ Manager.h | 38 +++++++ Recources.qrc | 5 + ScreenTranslator.pro | 32 ++++++ SelectionDialog.cpp | 88 +++++++++++++++ SelectionDialog.h | 34 ++++++ SelectionDialog.ui | 31 ++++++ SettingsEditor.cpp | 14 +++ SettingsEditor.h | 22 ++++ SettingsEditor.ui | 127 +++++++++++++++++++++ images/icon.png | Bin 0 -> 6644 bytes main.cpp | 13 +++ 14 files changed, 749 insertions(+) create mode 100644 GlobalActionHelper.cpp create mode 100644 GlobalActionHelper.h create mode 100644 Manager.cpp create mode 100644 Manager.h create mode 100644 Recources.qrc create mode 100644 ScreenTranslator.pro create mode 100644 SelectionDialog.cpp create mode 100644 SelectionDialog.h create mode 100644 SelectionDialog.ui create mode 100644 SettingsEditor.cpp create mode 100644 SettingsEditor.h create mode 100644 SettingsEditor.ui create mode 100644 images/icon.png create mode 100644 main.cpp diff --git a/GlobalActionHelper.cpp b/GlobalActionHelper.cpp new file mode 100644 index 0000000..d7b206d --- /dev/null +++ b/GlobalActionHelper.cpp @@ -0,0 +1,244 @@ +#include "GlobalActionHelper.h" + +#include + +#include +#include + +QHash, QAction*> GlobalActionHelper::actions_; + +bool GlobalActionHelper::nativeEventFilter(const QByteArray& eventType, + void* message, long* result) +{ + Q_UNUSED (eventType); + Q_UNUSED (result); + MSG* msg = static_cast(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); +} diff --git a/GlobalActionHelper.h b/GlobalActionHelper.h new file mode 100644 index 0000000..41ed160 --- /dev/null +++ b/GlobalActionHelper.h @@ -0,0 +1,28 @@ +#ifndef GLOBALACTIONHELPER_H +#define GLOBALACTIONHELPER_H + +// Some functions copied from QXT lib + +#include +#include + +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, 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 diff --git a/Manager.cpp b/Manager.cpp new file mode 100644 index 0000000..22cc075 --- /dev/null +++ b/Manager.cpp @@ -0,0 +1,73 @@ +#include "Manager.h" + +#include +#include +#include +#include +#include +#include + +#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 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) +{ + +} diff --git a/Manager.h b/Manager.h new file mode 100644 index 0000000..952ebb3 --- /dev/null +++ b/Manager.h @@ -0,0 +1,38 @@ +#ifndef MANAGER_H +#define MANAGER_H + +#include +#include + +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 diff --git a/Recources.qrc b/Recources.qrc new file mode 100644 index 0000000..264f123 --- /dev/null +++ b/Recources.qrc @@ -0,0 +1,5 @@ + + + images/icon.png + + diff --git a/ScreenTranslator.pro b/ScreenTranslator.pro new file mode 100644 index 0000000..cd6b7a8 --- /dev/null +++ b/ScreenTranslator.pro @@ -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 diff --git a/SelectionDialog.cpp b/SelectionDialog.cpp new file mode 100644 index 0000000..e77e1ea --- /dev/null +++ b/SelectionDialog.cpp @@ -0,0 +1,88 @@ +#include "SelectionDialog.h" +#include "ui_SelectionDialog.h" + +#include +#include +#include + +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 (event); + if (mouseEvent->button () == Qt::LeftButton) + { + startSelectPos_ = mouseEvent->pos (); + } + } + else if (event->type () == QEvent::MouseButtonRelease) + { + QMouseEvent* mouseEvent = static_cast (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 (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 (); +} diff --git a/SelectionDialog.h b/SelectionDialog.h new file mode 100644 index 0000000..9cd957c --- /dev/null +++ b/SelectionDialog.h @@ -0,0 +1,34 @@ +#ifndef SELECTIONDIALOG_H +#define SELECTIONDIALOG_H + +#include +#include + +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 diff --git a/SelectionDialog.ui b/SelectionDialog.ui new file mode 100644 index 0000000..020f0c4 --- /dev/null +++ b/SelectionDialog.ui @@ -0,0 +1,31 @@ + + + SelectionDialog + + + + 0 + 0 + 400 + 300 + + + + Dialog + + + + 0 + + + + + + + + + + + + + diff --git a/SettingsEditor.cpp b/SettingsEditor.cpp new file mode 100644 index 0000000..078a081 --- /dev/null +++ b/SettingsEditor.cpp @@ -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; +} diff --git a/SettingsEditor.h b/SettingsEditor.h new file mode 100644 index 0000000..d398ac2 --- /dev/null +++ b/SettingsEditor.h @@ -0,0 +1,22 @@ +#ifndef SETTINGSEDITOR_H +#define SETTINGSEDITOR_H + +#include + +namespace Ui { + class SettingsEditor; +} + +class SettingsEditor : public QDialog +{ + Q_OBJECT + + public: + explicit SettingsEditor(QWidget *parent = 0); + ~SettingsEditor(); + + private: + Ui::SettingsEditor *ui; +}; + +#endif // SETTINGSEDITOR_H diff --git a/SettingsEditor.ui b/SettingsEditor.ui new file mode 100644 index 0000000..fc45651 --- /dev/null +++ b/SettingsEditor.ui @@ -0,0 +1,127 @@ + + + SettingsEditor + + + + 0 + 0 + 400 + 300 + + + + Dialog + + + + + 30 + 240 + 341 + 32 + + + + Qt::Horizontal + + + QDialogButtonBox::Cancel|QDialogButtonBox::Ok + + + + + + 50 + 40 + 46 + 13 + + + + TextLabel + + + + + + 40 + 80 + 46 + 13 + + + + TextLabel + + + + + + 50 + 120 + 46 + 13 + + + + One time select + + + + + + 160 + 80 + 69 + 22 + + + + + + + 160 + 40 + 69 + 22 + + + + + + + + buttonBox + accepted() + SettingsEditor + accept() + + + 248 + 254 + + + 157 + 274 + + + + + buttonBox + rejected() + SettingsEditor + reject() + + + 316 + 260 + + + 286 + 274 + + + + + diff --git a/images/icon.png b/images/icon.png new file mode 100644 index 0000000000000000000000000000000000000000..17fc2c577ac8d248bba645111a42edce7ba6e572 GIT binary patch literal 6644 zcmVPx#1ZP1_K>z@;j|==^1poj532;bRa{vGi!vFvd!vV){sAK>D03UQkSaefwW^{L9 za%BKeVQFr3E>1;MAU{7pKR-VpGcGkQHRs9$VE_ObUP(kjRCr#+n|n;vSGLD_8xV=e zA1G=fCW?B^l@4{hbqXyE(4o~@`jBGn)Ul&bTI`c*Yv0hPPpGA(+S1mxdQIA^|B+}L zP0UT5;Fud76XQwL#)t_*l3uU1Cx_XOVyU}9TY_Rwb)?4DcYi!ip@7oxNNPqKfn+VuUfKPelP0M=a z4V(7rn>Gy+vfik(DG-oZ_nu7zeENH9Y|IDiY}DEfmPnuR>l-X~!-p1q<2AkkJ#PBM zqCfoDVj4cO_>G$^5oJ>#Aq@gD-dkHJk_W>n(D|$1u)@`^TM;A_@wpIU z^7%cNc5`Sy3j(I`d?x*5tgpAUjUQS{{YRGgVWY)wVyurC^9HE?+q(Eo?iB4GlIK#b*E@2Lf^dRLnG3fR)R!_7XrZd--*%eEBu2f`lqQSMvQb zeqVwYl+%6zo>Tn(I?Kfaav)#^)}IUk;~*eaV`Km#+P2TCP--Fb0gn3@cUZY)zN;{ zJ0Do}`)h6Kn)SAjDNq8bd61iB0EYo`96+bAZX2$C z4)7NMees2t?9%hAtm_2?A}&F~Maa1TN#`J;4bo0Q-f^bTVW!dn^{Ku!23}AL;Z=-V z%J_5ff-H<7osyA+8%{zP_!Qhfqvb{z#|D*KLzVgfZc35FTwiD8MqcJG^0!l zN*!eG`*7E@C@jS<1E3f1{eT}J;Q0YBu=WhVS3HkA7kGX81+(WM0ePJ<9Q5F#b9e- ze>?MWAIcoXJRBlxPBjs3xI$a^V>q;0b335C!ax{4!l0~Y=8)P1XIE#!St;9 zP+ySH2MOJ*3LTJe1`>|qb^929J0wV#DoB`zUbkSJ-%i3H@Xa;>>)(R)=M!wI8Du@I zf6u@_p@b~bj(c_iz8CPanjgg-09exqc!t~CGePiG0I#ezt9UB#`oxL=5%P#(NHFpU zKP2=+LN6qAK|(v@`WXKwNRTe;A)y))=7*Djz6n~guPfsLd^Bz!hubF;^)mpU4fuIj zzZ!NoGRRH_Y$X_-M2Yk3Hd;6C*~h#eAm|MOFPC<}V_jKZ;01hHmD%5);1yZ^WPk|$ zrZ#G;XGEO5hqT$4O2(8D2?LPO2MOJfaGvo`;(@J@Ae}Y_NtmbA2_iDkH(B|LlD2Cm zVapd53-~0!rxWyM0=@+BRdlr80sn~|Wd8k3dMbD90enB;{eU+jzLD!YmKS)rbR>8I zUs_@Ix8(tOyfQ$Dh#5ixafA3_#1WSSg9JY$^fPV`Y^tslW_8sM`4UjX>!fL}vL-@|aL1Adb?c$PaO%?*KszYQXRDWjmN_~AtYqz@tio#d6@;|*)@hUMs501;V88Zv^xM4rpnq&E_=?e^oe^*(xy3OyBKn&_2 z5KA}3rR~Z~@P@?@F&B@Rgrp#G+PDqt34o3TbP_Tat7}Oq1^i0DH}jw(u8#rEGf)r9 zodS~Pq`mf5pT)+G_+7z^?B!4V!xVEI64qG{B%Ie$OkB{))QmT*gosk~&PK)}Ns!__ z6%-`2cJi7E@TmYVWZr0LX#ji+41B(mq$C7h(Rt2oHG>pe^yt3^fmgtLxEh#BIG}gF`KRN+dtB }|aei-9_v)OmxGnl~{mR-k_oUNIF(<$e61H~`3K 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 + +#include + +int main(int argc, char *argv[]) +{ + QApplication a(argc, argv); +// a.setQuitOnLastWindowClosed (false);//DEBUG + + Manager manager; + + return a.exec(); +}