commit 6cd510e389a482934ed29a60a55737da1b0efc40 Author: MSN Date: Sat Nov 23 10:48:34 2013 +0400 in progress 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 0000000..17fc2c5 Binary files /dev/null and b/images/icon.png differ diff --git a/main.cpp b/main.cpp new file mode 100644 index 0000000..af44e71 --- /dev/null +++ b/main.cpp @@ -0,0 +1,13 @@ +#include + +#include + +int main(int argc, char *argv[]) +{ + QApplication a(argc, argv); +// a.setQuitOnLastWindowClosed (false);//DEBUG + + Manager manager; + + return a.exec(); +}