diff --git a/JsRoboKey.pro b/JsRoboKey.pro index 53face3..b9a3207 100644 --- a/JsRoboKey.pro +++ b/JsRoboKey.pro @@ -47,3 +47,6 @@ FORMS += dlgjsrobokey.ui VERSION = 130805 + +RESOURCES += \ + resources.qrc diff --git a/dlgjsrobokey.cpp b/dlgjsrobokey.cpp index 833fc36..eed111a 100644 --- a/dlgjsrobokey.cpp +++ b/dlgjsrobokey.cpp @@ -14,11 +14,16 @@ #include "jsrobokey.h" DlgJsRoboKey::DlgJsRoboKey(QWidget *parent) : - QDialog(parent), + QDialog(parent, Qt::Window | Qt::WindowSystemMenuHint + | Qt::WindowMinimizeButtonHint + | Qt::WindowMaximizeButtonHint + | Qt::WindowCloseButtonHint), ui(new Ui::DlgJsRoboKey), m_pjsrobokey(NULL), m_jsengine(NULL) { ui->setupUi(this); + ui->memoInstaScript->setSuppressCtrlEnter(true); + connect(ui->memoInstaScript, SIGNAL(onCtrlEnter()), this, SLOT(on_btnInstaRun_clicked())); m_pjsrobokey = new JsRoboKey(this); @@ -49,9 +54,126 @@ DlgJsRoboKey::DlgJsRoboKey(QWidget *parent) : editor.setColor(JSEdit::BracketError, QColor("#A82224")); editor.setColor(JSEdit::FoldIndicator, QColor("#555555")); + createActions(); + createTrayIcon(); + + connect(trayIcon, SIGNAL(messageClicked()), this, SLOT(on_trayMessageClicked())); + connect(trayIcon, SIGNAL(activated(QSystemTrayIcon::ActivationReason)), + this, SLOT(iconActivated(QSystemTrayIcon::ActivationReason))); + + setIcon(1); + trayIcon->show(); + + + //initalize the v8 engine initialize(); } +void DlgJsRoboKey::createActions() +{ + minimizeAction = new QAction(tr("Mi&nimize"), this); + connect(minimizeAction, SIGNAL(triggered()), this, SLOT(hide())); + + maximizeAction = new QAction(tr("Ma&ximize"), this); + connect(maximizeAction, SIGNAL(triggered()), this, SLOT(showMaximized())); + + restoreAction = new QAction(tr("&Restore"), this); + connect(restoreAction, SIGNAL(triggered()), this, SLOT(showNormal())); + + quitAction = new QAction(tr("&Quit"), this); + connect(quitAction, SIGNAL(triggered()), qApp, SLOT(quit())); +} + + +void DlgJsRoboKey::createTrayIcon() +{ + trayIconMenu = new QMenu(this); + trayIconMenu->addAction(minimizeAction); + trayIconMenu->addAction(maximizeAction); + trayIconMenu->addAction(restoreAction); + trayIconMenu->addSeparator(); + trayIconMenu->addAction(quitAction); + + trayIcon = new QSystemTrayIcon(this); + trayIcon->setContextMenu(trayIconMenu); +} + +void DlgJsRoboKey::showTrayMessage(const QString& title, const QString& body, const QJSValue &callback, + int iicon, int ms_duration, + const QString& action, const QString& param1) + { + + //actions are to be defined in nature + //TODO: notice, this will screw up the previous callback, does it matter? + trayJsCallback = callback; + trayAction = action; + trayParam1 = param1; + // NoIcon, Information, Warning, Critical + QSystemTrayIcon::MessageIcon icon = (QSystemTrayIcon::MessageIcon)iicon; + if (ms_duration == 0){ ms_duration = 3500; } + trayIcon->showMessage(title, body, icon, ms_duration); + } + + +void DlgJsRoboKey::setVisible(bool visible) +{ + minimizeAction->setEnabled(visible); + maximizeAction->setEnabled(!isMaximized()); + restoreAction->setEnabled(isMaximized() || !visible); + QDialog::setVisible(visible); +} + +void DlgJsRoboKey::closeEvent(QCloseEvent *event) + { + if (trayIcon->isVisible()) { + showTrayMessage("JsRoboKey is still running.", + "To exit the program completely and all running scripts, Right click -> quit "); + hide(); + event->ignore(); + } + } + +void DlgJsRoboKey::on_trayMessageClicked() + { + //TODO: FIX: this stupid trayJsCallback always ends up being undefined. + //TODO: depending on the action we need to do something + if (trayJsCallback.isCallable()){ + trayJsCallback.call(); + //it was already called, now make it undefined + } + trayJsCallback = QJSValue(); + //m_pjsrobokey->alert("tray clicked!!",""); + } + +void DlgJsRoboKey::iconActivated(QSystemTrayIcon::ActivationReason reason) + { + switch (reason) { + case QSystemTrayIcon::Trigger: + case QSystemTrayIcon::DoubleClick: + //restore the app + showNormal(); + break; + case QSystemTrayIcon::MiddleClick: + //what the heck are we going to do with a middle click? + break; + default: + ; + } + } + +void DlgJsRoboKey::setIcon(int index) +{ + QIcon icon = QIcon(tr(":/jsrobokeyicon%1.png").arg(index)); + trayIcon->setIcon(icon); + setWindowIcon(icon); +} + +void DlgJsRoboKey::showTrayMessage(const QString &title, const QString &body) +{ + QJSValue undefined; + showTrayMessage(title, body, undefined); +} + DlgJsRoboKey::~DlgJsRoboKey() { delete m_jsengine; @@ -69,14 +191,18 @@ void DlgJsRoboKey::initialize() m_jsengine = new QJSEngine(this); m_rk = m_jsengine->newQObject(m_pjsrobokey); m_jsengine->globalObject().setProperty("JsRoboKey", m_rk); + m_jsengine->globalObject().setProperty("__APPFILEPATH__", QCoreApplication::applicationFilePath()); + m_jsengine->globalObject().setProperty("__APPDIRPATH__", QCoreApplication::applicationDirPath()); + m_jsengine->globalObject().setProperty("__HOMEPATH__", QDir::homePath()); + + //QStandardPaths::standardLocations(QStandardPaths::DesktopLocation); //allow rk for short //make some functions global scope loadJS("jsrk = rk = JsRoboKey; " "alert = rk.alert; " "include = rk.include; " - "require = rk.require" - "__FILE__ = 'JsRoboKey::initialize()'; ", "JsRoboKey::initialize()"); + "require = rk.require", "JsRoboKey::initialize()"); } @@ -94,11 +220,21 @@ bool DlgJsRoboKey::loadJSFile(const QString &file) return loadJS(contents, file); } + bool DlgJsRoboKey::loadJS(const QString &code, const QString& module_or_filename) -{ +{ + static int num_loadjs_calls = 0; + num_loadjs_calls++; + QString plural = (num_loadjs_calls > 1 ? "s" : ""); + trayIcon->setToolTip(tr("JsRoboKey (%1 loadJS call%2 made.)") + .arg(num_loadjs_calls).arg(plural)); + m_lastException = tr(""); m_lastRunCode = code; m_lastRunFileOrModule = module_or_filename; + //prior to evaluation we want to store the module_or_filename in __FILE__ + //that the script itself can use + m_jsengine->globalObject().setProperty("__FILE__", QJSValue(module_or_filename)); m_lastRunVal = m_jsengine->evaluate(code, module_or_filename); if (m_lastRunVal.isError()) { diff --git a/dlgjsrobokey.h b/dlgjsrobokey.h index 9d123c2..09f8c43 100644 --- a/dlgjsrobokey.h +++ b/dlgjsrobokey.h @@ -13,6 +13,8 @@ #include #include #include +#include +#include #include "jsrobokey.h" class JsRoboKey; @@ -37,12 +39,26 @@ class DlgJsRoboKey : public QDialog bool loadJS(const QString& code, const QString &module_or_filename); QJSEngine* jsengine(); + void setIcon(int index = 1); + + void showTrayMessage(const QString &title, const QString &body); + void showTrayMessage(const QString &title, const QString &body, const QJSValue &callback, int iicon = 0, + int ms_duration = 3500, const QString &action="", const QString ¶m1=""); + + void setVisible(bool visible); + void createTrayIcon(); + void createActions(); private slots: void on_btnInstaRun_clicked(); - void on_btnUnloadAll_clicked(); + void on_trayMessageClicked(); + void iconActivated(QSystemTrayIcon::ActivationReason reason); + +protected: + virtual void closeEvent(QCloseEvent *event); private: + Ui::DlgJsRoboKey *ui; QJSEngine* m_jsengine; QJSValue m_rk; @@ -51,6 +67,20 @@ private slots: QString m_lastRunCode; QString m_lastRunFileOrModule; JsRoboKey* m_pjsrobokey; + + + QAction *minimizeAction; + QAction *maximizeAction; + QAction *restoreAction; + QAction *quitAction; + + + QSystemTrayIcon *trayIcon; + QMenu *trayIconMenu; + + QString trayAction; + QString trayParam1; + QJSValue trayJsCallback; }; diff --git a/jsedit.cpp b/jsedit.cpp index 96c64cb..2d5dc21 100644 --- a/jsedit.cpp +++ b/jsedit.cpp @@ -824,6 +824,25 @@ bool JSEdit::isFolded(int line) const return !block.isVisible(); } +void JSEdit::keyPressEvent(QKeyEvent *e) +{ + if ((e->modifiers()==Qt::ControlModifier)){ + if ((e->key()==Qt::Key_Return)){ + emit onCtrlEnter(); + if (m_suppressCtrlEnter){ + return; //suppress ctrl enter + } + }else if (e->key()==Qt::Key_Space){ + emit onCtrlSpace(); + if (m_suppressCtrlSpace){ + return; //suppress ctrl enter + } + } + } + e->accept(); + QPlainTextEdit::keyPressEvent(e); +} + void JSEdit::fold(int line) { QTextBlock startBlock = document()->findBlockByNumber(line - 1); @@ -1037,3 +1056,25 @@ void JSEdit::mark(const QString &str, Qt::CaseSensitivity sens) { d_ptr->highlighter->mark(str, sens); } + + +bool JSEdit::suppressCtrlSpace() const +{ + return m_suppressCtrlSpace; +} + +void JSEdit::setSuppressCtrlSpace(bool suppressCtrlSpace) +{ + m_suppressCtrlSpace = suppressCtrlSpace; +} + +bool JSEdit::suppressCtrlEnter() const +{ + return m_suppressCtrlEnter; +} + +void JSEdit::setSuppressCtrlEnter(bool suppressCtrlEnter) +{ + m_suppressCtrlEnter = suppressCtrlEnter; +} + diff --git a/jsedit.h b/jsedit.h index 104856e..eb0463f 100644 --- a/jsedit.h +++ b/jsedit.h @@ -82,6 +82,14 @@ class JSEdit: public QPlainTextEdit bool isFoldable(int line) const; bool isFolded(int line) const; + void keyPressEvent(QKeyEvent *e); + + bool suppressCtrlEnter() const; + void setSuppressCtrlEnter(bool suppressCtrlEnter); + + bool suppressCtrlSpace() const; + void setSuppressCtrlSpace(bool suppressCtrlSpace); + public slots: void updateSidebar(); void mark(const QString &str, Qt::CaseSensitivity sens = Qt::CaseInsensitive); @@ -94,6 +102,13 @@ public slots: void unfold(int line); void toggleFold(int line); +signals: + void onCtrlEnter(); + void onCtrlSpace(); +private: + bool m_suppressCtrlEnter; + bool m_suppressCtrlSpace; + protected: void resizeEvent(QResizeEvent *e); void wheelEvent(QWheelEvent *e); diff --git a/jsrobokey.cpp b/jsrobokey.cpp index c4a2af6..72e9549 100644 --- a/jsrobokey.cpp +++ b/jsrobokey.cpp @@ -118,6 +118,19 @@ bool JsRoboKey::closeWindow(int hwnd) return false; } +bool JsRoboKey::trayMsg(const QString &title, const QString &body) +{ + app()->showTrayMessage(title, body); + return true; +} + +bool JsRoboKey::trayMsg(const QString &title, const QString &body, const QJSValue& callback, + int iicon, int ms_duration) +{ + app()->showTrayMessage(title, body, callback, iicon, ms_duration); + return true; +} + bool JsRoboKey::fileExists(const QString &file) { QFile f(file); diff --git a/jsrobokey.h b/jsrobokey.h index 96583c9..640f1a1 100644 --- a/jsrobokey.h +++ b/jsrobokey.h @@ -91,6 +91,11 @@ public slots: QString getWindowText(int hwnd); bool closeWindow(int hwnd); + bool trayMsg(const QString &title, const QString &body); + bool trayMsg(const QString &title, const QString &body, const QJSValue &callback, + int iicon = 0, int ms_duration = 3500); + + //---what-the-hey-we-gotta-have-one-of-these void helloWorld(){ qDebug() << "hello World"; alert("Hello world"); } //-------------------------------------------- diff --git a/resources.qrc b/resources.qrc new file mode 100644 index 0000000..c4ef79d --- /dev/null +++ b/resources.qrc @@ -0,0 +1,7 @@ + + + jsrobokeyicon1.icns + jsrobokeyicon1.ico + jsrobokeyicon1.png + +