]> Some of my projects - launcher.git/commitdiff
Init
authorAPTX <marek321@gmail.com>
Mon, 5 Nov 2012 17:21:47 +0000 (18:21 +0100)
committerAPTX <marek321@gmail.com>
Mon, 5 Nov 2012 17:21:47 +0000 (18:21 +0100)
40 files changed:
.gitignore [new file with mode: 0644]
launcher.pro [new file with mode: 0644]
launcher/icon.png [new file with mode: 0644]
launcher/inputwidget.cpp [new file with mode: 0644]
launcher/inputwidget.h [new file with mode: 0644]
launcher/launcher.cpp [new file with mode: 0644]
launcher/launcher.h [new file with mode: 0644]
launcher/launcher.pro [new file with mode: 0644]
launcher/main.cpp [new file with mode: 0644]
launcher/mainwindow.cpp [new file with mode: 0644]
launcher/mainwindow.h [new file with mode: 0644]
launcher/plugin.cpp [new file with mode: 0644]
launcher/plugin.h [new file with mode: 0644]
launcher/pluginthread.cpp [new file with mode: 0644]
launcher/pluginthread.h [new file with mode: 0644]
launcher/qml/Components/ResultDelegate.qml [new file with mode: 0644]
launcher/qml/view.qml [new file with mode: 0644]
launcher/resources.qrc [new file with mode: 0644]
launcher/resultmodel.cpp [new file with mode: 0644]
launcher/resultmodel.h [new file with mode: 0644]
launcher/tray.cpp [new file with mode: 0644]
launcher/tray.h [new file with mode: 0644]
pluginapi/launcherpluginbase.cpp [new file with mode: 0644]
pluginapi/launcherpluginbase.h [new file with mode: 0644]
pluginapi/launcherplugininterface.h [new file with mode: 0644]
pluginapi/loaderplugin.cpp [new file with mode: 0644]
pluginapi/pluginapi.pri [new file with mode: 0644]
pluginapi/pluginapi.pro [new file with mode: 0644]
pluginapi/pluginapi_global.h [new file with mode: 0644]
pluginapi/reply.cpp [new file with mode: 0644]
pluginapi/reply.h [new file with mode: 0644]
plugins/localmylist/localmylist.pro [new file with mode: 0644]
plugins/localmylist/localmylistplugin.cpp [new file with mode: 0644]
plugins/localmylist/localmylistplugin.h [new file with mode: 0644]
plugins/localmylist/localmylistplugin_global.h [new file with mode: 0644]
plugins/plugins.pro [new file with mode: 0644]
plugins/test/test.cpp [new file with mode: 0644]
plugins/test/test.h [new file with mode: 0644]
plugins/test/test.pro [new file with mode: 0644]
plugins/test/test_global.h [new file with mode: 0644]

diff --git a/.gitignore b/.gitignore
new file mode 100644 (file)
index 0000000..2f6642b
--- /dev/null
@@ -0,0 +1,76 @@
+# This file is used to ignore files which are generated
+# ----------------------------------------------------------------------------
+
+*~
+*.a
+*.core
+*.moc
+*.o
+*.obj
+*.orig
+*.rej
+*.so
+*_pch.h.cpp
+*_resource.rc
+*.qm
+.#*
+*.*#
+core
+.qmake.cache
+tags
+.DS_Store
+*.debug
+Makefile*
+*.prl
+*.app
+moc_*.cpp
+ui_*.h
+qrc_*.cpp
+
+# qtcreator generated files
+*.pro.user
+*.pro.user.*
+*.autosave
+
+# xemacs temporary files
+*.flc
+
+# Vim temporary files
+.*.swp
+
+# Visual Studio generated files
+*.ib_pdb_index
+*.idb
+*.ilk
+*.pdb
+*.sln
+*.suo
+*.vcproj
+*vcproj.*.*.user
+*.ncb
+*.exp
+
+# MinGW generated files
+*.Debug
+*.Release
+
+# Directories to ignore
+# ---------------------
+
+build
+debug
+release
+lib/qtsingleapplication/lib
+lib/qtsingleapplication/examples
+lib/qtsingleapplication/doc
+.tmp
+qtc-gdbmacros
+
+# Binaries
+# --------
+build/*.dll
+build/*.lib
+build/*.exe
+build/*.so*
+
+
diff --git a/launcher.pro b/launcher.pro
new file mode 100644 (file)
index 0000000..f70f582
--- /dev/null
@@ -0,0 +1,6 @@
+TEMPLATE = subdirs
+CONFIG += ordered
+
+SUBDIRS += pluginapi \
+       launcher \
+       plugins
diff --git a/launcher/icon.png b/launcher/icon.png
new file mode 100644 (file)
index 0000000..a6b97e6
Binary files /dev/null and b/launcher/icon.png differ
diff --git a/launcher/inputwidget.cpp b/launcher/inputwidget.cpp
new file mode 100644 (file)
index 0000000..01d6f94
--- /dev/null
@@ -0,0 +1,12 @@
+#include "inputwidget.h"
+
+InputWidget::InputWidget(QWidget *parent) :
+       QLineEdit(parent)
+{
+
+}
+
+QSize InputWidget::minimumSizeHint()
+{
+       return QSize(400, 50);
+}
diff --git a/launcher/inputwidget.h b/launcher/inputwidget.h
new file mode 100644 (file)
index 0000000..36ce4ad
--- /dev/null
@@ -0,0 +1,20 @@
+#ifndef INPUTWIDGET_H
+#define INPUTWIDGET_H
+
+#include <QLineEdit>
+
+class InputWidget : public QLineEdit
+{
+       Q_OBJECT
+public:
+       explicit InputWidget(QWidget *parent = 0);
+       
+signals:
+       
+public slots:
+//     void input
+protected:
+       QSize minimumSizeHint();
+};
+
+#endif // INPUTWIDGET_H
diff --git a/launcher/launcher.cpp b/launcher/launcher.cpp
new file mode 100644 (file)
index 0000000..1e2004d
--- /dev/null
@@ -0,0 +1,147 @@
+#include "launcher.h"
+
+#include <QAction>
+#include <QMenu>
+#include <QDir>
+#include <QFileInfo>
+#include <QxtGlobalShortcut>
+
+#include "mainwindow.h"
+#include "tray.h"
+#include "plugin.h"
+#include "launcherpluginbase.h"
+#include "resultmodel.h"
+
+#include <QDebug>
+
+Launcher::Launcher(int argc, char **argv) :
+       QApplication(argc, argv)
+{
+       m_instance = this;
+       m_resultModel = new ResultModel(this);
+       m_mainWindow = new MainWindow;
+       m_tray = new Tray;
+
+       connect(this, SIGNAL(aboutToQuit()), m_tray, SLOT(hide()));
+
+       qRegisterMetaType<Reply>("Reply");
+       loadPlugins();
+
+       setWindowIcon(QIcon(":/icon.png"));
+       m_tray->setIcon(windowIcon());
+
+       showAction = new QAction("Show", this);
+       showAction->setShortcut(QKeySequence("Alt+Space"));
+       connect(showAction, SIGNAL(triggered()), m_mainWindow, SLOT(activate()));
+
+       showShortcut = new QxtGlobalShortcut(m_mainWindow);
+       connect(showShortcut, SIGNAL(activated()), showAction, SLOT(trigger()));
+       showShortcut->setShortcut(showAction->shortcut());
+
+       quitAction = new QAction("&Quit", this);
+       connect(quitAction, SIGNAL(triggered()), qApp, SLOT(quit()));
+
+
+       QMenu *menu = new QMenu;
+       menu->addAction(showAction);
+       menu->addSeparator();
+       menu->addAction(quitAction);
+       m_tray->setContextMenu(menu);
+
+       connect(m_mainWindow, SIGNAL(commandChanged(QString)), this, SLOT(queryPlugins(QString)));
+       connect(m_mainWindow, SIGNAL(commandChanged(QString)), m_resultModel, SLOT(commandChanged(QString)));
+       m_tray->show();
+
+}
+
+Launcher::~Launcher()
+{
+       unloadPlugins();
+       m_instance = 0;
+}
+
+MainWindow *Launcher::mainWindow() const
+{
+       return m_mainWindow;
+}
+
+Tray *Launcher::tray() const
+{
+       return m_tray;
+}
+
+ResultModel *Launcher::resultModel() const
+{
+       return m_resultModel;
+}
+
+void Launcher::queryPlugins(const QString &cmd)
+{
+       if (cmd.isEmpty())
+               return;
+
+       foreach (Plugin *p, plugins)
+       {
+               p->processCommand(cmd);
+       }
+}
+
+void Launcher::updateResults()
+{
+       /*
+       Plugin *p = qobject_cast<Plugin*>(sender());
+
+       foreach(const Result &r, p->latestResult().results)
+       {
+               qDebug() << r.match << r.description;
+       }
+       */
+}
+
+void Launcher::loadPlugins()
+{
+       QDir dir(QDir::current());
+       QStringList nameFilter;
+#if defined(Q_OS_WIN)
+       nameFilter << "*_plugin.dll";
+#elif defined(Q_OS_UNIX)
+       nameFilter << "*_plugin.so";
+#endif
+
+       QFileInfoList pluginFiles = dir.entryInfoList(nameFilter, QDir::Files);
+
+       foreach (const QFileInfo &file, pluginFiles)
+       {
+               qDebug() << "Loading plugin" << file.fileName();
+               Plugin *plugin = new Plugin(file.absoluteFilePath());
+               connect(plugin, SIGNAL(resultRecieved()), this, SLOT(updateResults()));
+               connect(plugin, SIGNAL(resultRecieved()), m_resultModel, SLOT(updateResults()));
+               if (!plugin->load())
+               {
+                       qDebug() << "Load failed";
+                       continue;
+               }
+
+               plugins.append(plugin);
+
+       }
+}
+
+void Launcher::unloadPlugins()
+{
+       while (plugins.count())
+       {
+               Plugin *p = plugins.takeLast();
+               p->unload();
+               p->deleteLater();
+       }
+       plugins.clear();
+}
+
+Launcher *Launcher::instance()
+{
+       return m_instance;
+}
+
+
+Launcher *Launcher::m_instance = 0;
diff --git a/launcher/launcher.h b/launcher/launcher.h
new file mode 100644 (file)
index 0000000..8142350
--- /dev/null
@@ -0,0 +1,56 @@
+#ifndef LAUNCHER_H
+#define LAUNCHER_H
+
+#include <QApplication>
+#include "reply.h"
+
+class MainWindow;
+class Tray;
+class QAction;
+class QxtGlobalShortcut;
+
+class Plugin;
+class ResultModel;
+
+class Launcher : public QApplication
+{
+       Q_OBJECT
+public:
+       explicit Launcher(int argc, char **argv);
+       ~Launcher();
+
+       MainWindow *mainWindow() const;
+       Tray *tray() const;
+       ResultModel *resultModel() const;
+
+
+public slots:
+       void queryPlugins(const QString &cmd);
+       void updateResults();
+
+private:
+       void loadPlugins();
+       void unloadPlugins();
+
+       MainWindow *m_mainWindow;
+       Tray *m_tray;
+
+       QAction *showAction;
+       QAction *quitAction;
+       QxtGlobalShortcut *showShortcut;
+
+       QList<Plugin *> plugins;
+
+       ResultModel *m_resultModel;
+
+       static Launcher *m_instance;
+public:
+       static Launcher *instance();
+};
+
+#if defined(qApp)
+#      undef qApp
+#endif
+#define qApp Launcher::instance()
+
+#endif // LAUNCHER_H
diff --git a/launcher/launcher.pro b/launcher/launcher.pro
new file mode 100644 (file)
index 0000000..4fd4a0a
--- /dev/null
@@ -0,0 +1,51 @@
+QT += core gui declarative
+CONFIG += qxt
+QXT *= gui
+
+DESTDIR = ../build
+
+greaterThan(QT_MAJOR_VERSION, 4): QT += widgets
+
+TARGET = launcher
+TEMPLATE = app
+
+
+SOURCES += main.cpp \
+       mainwindow.cpp \
+       inputwidget.cpp \
+       launcher.cpp \
+       tray.cpp
+
+HEADERS += mainwindow.h \
+       inputwidget.h \
+       launcher.h \
+       tray.h
+
+RESOURCES += \
+       resources.qrc
+
+include(../pluginapi/pluginapi.pri)
+
+HEADERS += \
+    pluginthread.h
+
+SOURCES += \
+    pluginthread.cpp
+
+OTHER_FILES += \
+    qml/view.qml
+
+OTHER_FILES += \
+    qml/Components/ResultDelegate.qml
+
+HEADERS += \
+    resultmodel.h
+
+SOURCES += \
+    resultmodel.cpp
+
+HEADERS += \
+    plugin.h
+
+SOURCES += \
+    plugin.cpp
diff --git a/launcher/main.cpp b/launcher/main.cpp
new file mode 100644 (file)
index 0000000..e817df9
--- /dev/null
@@ -0,0 +1,9 @@
+#include "mainwindow.h"
+#include "launcher.h"
+
+int main(int argc, char *argv[])
+{
+       Launcher a(argc, argv);
+
+       return a.exec();
+}
diff --git a/launcher/mainwindow.cpp b/launcher/mainwindow.cpp
new file mode 100644 (file)
index 0000000..7cde7a2
--- /dev/null
@@ -0,0 +1,148 @@
+#include "mainwindow.h"
+#include <QKeyEvent>
+#include <QFocusEvent>
+#include <QDesktopWidget>
+#include <QVBoxLayout>
+#include <QDeclarativeView>
+#include <QDeclarativeContext>
+
+#include <QProcess>
+#include <QDesktopServices>
+
+#include "launcher.h"
+#include "resultmodel.h"
+#include "inputwidget.h"
+
+#include <QDebug>
+
+MainWindow::MainWindow(QWidget *parent)
+       : QWidget(parent)
+{
+       setWindowFlags(Qt::FramelessWindowHint | Qt::Tool | Qt::WindowStaysOnTopHint);
+       setAttribute(Qt::WA_TranslucentBackground);
+       desktopWidget = new QDesktopWidget();
+       connect(desktopWidget, SIGNAL(resized(int)), this, SLOT(position()));
+       setupUi();
+}
+
+MainWindow::~MainWindow()
+{
+       delete desktopWidget;
+}
+
+void MainWindow::keyPressEvent(QKeyEvent *e)
+{
+       switch (e->key())
+       {
+               case Qt::Key_Escape:
+                       hide();
+                       e->accept();
+               break;
+               case Qt::Key_Down:
+                       qApp->resultModel()->setSelectedIndex(qApp->resultModel()->selectedIndex() + 1);
+                       e->accept();
+               break;
+               case Qt::Key_Up:
+                       qApp->resultModel()->setSelectedIndex(qApp->resultModel()->selectedIndex() - 1);
+                       e->accept();
+               break;
+       }
+}
+
+void MainWindow::resizeEvent(QResizeEvent *e)
+{
+       QWidget::resizeEvent(e);
+       position();
+}
+
+bool MainWindow::event(QEvent *e)
+{
+       if (e->type() == QEvent::WindowDeactivate)
+               hide();
+
+       return QWidget::event(e);
+}
+
+void MainWindow::position()
+{
+       QRect r = desktopWidget->screenGeometry();
+       move(r.center() - QPoint(width() / 2, height() / 2));
+}
+
+void MainWindow::setupUi()
+{
+       inputWidget = new InputWidget(this);
+       connect(inputWidget, SIGNAL(returnPressed()), this, SLOT(handleReturn()));
+       connect(inputWidget, SIGNAL(textEdited(QString)), this, SIGNAL(commandChanged(QString)));
+
+       view = new QDeclarativeView(this);
+       view->setMinimumHeight(60*5);
+
+       QDeclarativeContext *ctxt = view->rootContext();
+       ctxt->setContextProperty("resultModel", qApp->resultModel());
+       ctxt->setContextProperty("mainWindow", this);
+
+       view->setSource(QUrl("qrc:/qml/view.qml"));
+       view->setResizeMode(QDeclarativeView::SizeRootObjectToView);
+
+
+       view->setAttribute(Qt::WA_OpaquePaintEvent);
+       view->setAttribute(Qt::WA_NoSystemBackground);
+       view->viewport()->setAttribute(Qt::WA_OpaquePaintEvent);
+       view->viewport()->setAttribute(Qt::WA_NoSystemBackground);
+
+       QVBoxLayout *l = new QVBoxLayout();
+       l->setContentsMargins(0, 0, 0, 0);
+       l->addWidget(inputWidget);
+       l->addWidget(view);
+       setLayout(l);
+       resize(700, height());
+}
+
+void MainWindow::activate()
+{
+       show();
+       raise();
+       activateWindow();
+       inputWidget->setFocus();
+}
+
+void MainWindow::handleReturn()
+{
+       QString command = inputWidget->text();
+
+       if (command == "qqq")
+       {
+               qApp->quit();
+               hide();
+               return;
+       }
+
+       hide();
+
+       if (command.isEmpty())
+               return;
+
+       Result r = qApp->resultModel()->selectedResult();
+
+       if (r.command.isEmpty())
+       {
+               qDebug() << "empty command";
+               return;
+       }
+
+       bool success = false;
+       switch (r.commandType)
+       {
+               case RunCommand:
+                       success = QProcess::startDetached(r.command, r.args);
+               break;
+               case OpenCommand:
+qDebug() << "opening" << ("file://" + r.command);
+                       success = QDesktopServices::openUrl(QUrl::fromUserInput(r.command));
+               break;
+       }
+       qDebug() << "did it work?" << success;
+       inputWidget->clear();
+       qApp->resultModel()->clear();
+}
diff --git a/launcher/mainwindow.h b/launcher/mainwindow.h
new file mode 100644 (file)
index 0000000..dae0d2d
--- /dev/null
@@ -0,0 +1,42 @@
+#ifndef MAINWINDOW_H
+#define MAINWINDOW_H
+
+#include <QWidget>
+
+
+class QDesktopWidget;
+class QDeclarativeView;
+class InputWidget;
+
+class MainWindow : public QWidget
+{
+       Q_OBJECT
+       
+public:
+       MainWindow(QWidget *parent = 0);
+       ~MainWindow();
+
+public slots:
+       void activate();
+       void handleReturn();
+
+protected:
+       void keyPressEvent(QKeyEvent *e);
+       void resizeEvent(QResizeEvent *e);
+       bool event(QEvent *);
+
+protected slots:
+       void position();
+
+signals:
+       void commandChanged(const QString &cmd);
+
+private:
+       void setupUi();
+
+       QDesktopWidget *desktopWidget;
+       InputWidget *inputWidget;
+       QDeclarativeView *view;
+};
+
+#endif // MAINWINDOW_H
diff --git a/launcher/plugin.cpp b/launcher/plugin.cpp
new file mode 100644 (file)
index 0000000..c6c1488
--- /dev/null
@@ -0,0 +1,84 @@
+#include "plugin.h"
+
+#include "pluginthread.h"
+#include "launcherpluginbase.h"
+
+Plugin::Plugin(const QString &file, QObject *parent) : QObject(parent),
+       m_pluginThread(new PluginThread(file, this)), executing(false), m_status(Unloaded)
+{
+       unload();
+}
+
+bool Plugin::isCurrentResult() const
+{
+       return !executing && m_lastProcessedCommand == m_latestCommand;
+}
+
+Plugin::Status Plugin::status() const
+{
+       return m_status;
+}
+
+Reply Plugin::latestResult() const
+{
+       return m_latestResult;
+}
+
+Reply Plugin::previousResult() const
+{
+       return m_previousResult;
+}
+
+LauncherPluginBase *Plugin::pluginInstance()
+{
+       return m_pluginThread->plugin();
+}
+
+bool Plugin::load()
+{
+       if (m_status != Unloaded)
+               return false;
+
+       bool r = m_pluginThread->startThread();
+       connect(m_pluginThread->plugin(), SIGNAL(replyReady(Reply)), this, SLOT(handleReply(Reply)), Qt::QueuedConnection);
+       m_status = r ? Loaded : Error;
+
+       return r;
+}
+
+void Plugin::unload()
+{
+       if (m_status != Loaded)
+               return;
+       m_pluginThread->stopThread();
+       m_status = Unloaded;
+}
+
+void Plugin::processCommand(const QString &cmd)
+{
+       if (m_lastProcessedCommand == cmd)
+               return;
+
+       m_latestCommand = cmd;
+
+       if (executing)
+               return;
+       executing = true;
+
+       m_lastProcessedCommand = cmd;
+
+       QMetaObject::invokeMethod(m_pluginThread->plugin(), "processCommand", Qt::QueuedConnection,
+                                                         Q_ARG(QString, cmd));
+}
+
+void Plugin::handleReply(const Reply &reply)
+{
+       m_previousResult = m_latestResult;
+       m_latestResult = reply;
+       executing = false;
+
+       if (m_lastProcessedCommand != m_latestCommand)
+               processCommand(m_latestCommand);
+
+       emit resultRecieved();
+}
diff --git a/launcher/plugin.h b/launcher/plugin.h
new file mode 100644 (file)
index 0000000..bfcafd7
--- /dev/null
@@ -0,0 +1,55 @@
+#ifndef PLUGIN_H
+#define PLUGIN_H
+
+#include <QObject>
+
+#include "reply.h"
+
+class PluginThread;
+class LauncherPluginBase;
+
+class Plugin : public QObject
+{
+       Q_OBJECT
+public:
+       enum Status {
+               Unloaded,
+               Loaded,
+               Error
+       };
+
+       explicit Plugin(const QString &file, QObject *parent = 0);
+       
+       bool isCurrentResult() const;
+       Status status() const;
+       Reply latestResult() const;
+       Reply previousResult() const;
+
+       LauncherPluginBase *pluginInstance();
+
+signals:
+       void resultRecieved();
+
+public slots:
+       bool load();
+       void unload();
+
+       void processCommand(const QString &cmd);
+
+private slots:
+       void handleReply(const Reply &reply);
+
+private:
+       bool executing;
+       Status m_status;
+
+       QString m_lastProcessedCommand;
+       QString m_latestCommand;
+
+       Reply m_previousResult;
+       Reply m_latestResult;
+
+       PluginThread *m_pluginThread;
+};
+
+#endif // PLUGIN_H
diff --git a/launcher/pluginthread.cpp b/launcher/pluginthread.cpp
new file mode 100644 (file)
index 0000000..0e0e7cd
--- /dev/null
@@ -0,0 +1,63 @@
+#include "pluginthread.h"
+
+#include <QPluginLoader>
+#include "launcherpluginbase.h"
+
+#include <QDebug>
+
+PluginThread::PluginThread(const QString &file, QObject *parent) : QThread(parent),
+       loaded(false), m_file(file), m_pluginLoader(0), m_plugin(0), m_waitStarted(0)
+{
+}
+
+bool PluginThread::startThread()
+{
+       start();
+       m_waitStarted.acquire();
+       return loaded;
+}
+
+void PluginThread::stopThread()
+{
+       quit();
+       m_waitStarted.acquire();
+}
+
+LauncherPluginBase *PluginThread::plugin()
+{
+       return m_plugin;
+}
+
+void PluginThread::run()
+{
+       m_pluginLoader = new QPluginLoader(m_file);
+       Q_ASSERT(m_pluginLoader->thread() == this);
+
+       if (!m_pluginLoader->load())
+       {
+               qDebug() << "Load error:" << m_pluginLoader->errorString();
+               m_waitStarted.release();
+               delete m_pluginLoader;
+               return;
+       }
+       qDebug() << "loaded!";
+       loaded = true;
+
+       m_plugin = qobject_cast<LauncherPluginBase*>(m_pluginLoader->instance());
+       m_waitStarted.release();
+       m_plugin->init();
+
+       exec();
+
+       m_plugin->deinit();
+       bool s = m_pluginLoader->unload();
+       m_plugin = 0;
+       loaded = false;
+
+       delete m_pluginLoader;
+
+       qDebug() << "Unload succeeded?" << s;
+
+       m_waitStarted.release();
+}
+
diff --git a/launcher/pluginthread.h b/launcher/pluginthread.h
new file mode 100644 (file)
index 0000000..cc8707a
--- /dev/null
@@ -0,0 +1,32 @@
+#ifndef PLUGINTHREAD_H
+#define PLUGINTHREAD_H
+
+#include <QThread>
+#include <QSemaphore>
+
+class QPluginLoader;
+class LauncherPluginBase;
+
+class PluginThread : public QThread
+{
+       Q_OBJECT
+public:
+       explicit PluginThread(const QString &file, QObject *parent = 0);
+
+       bool startThread();
+       void stopThread();
+       LauncherPluginBase *plugin();
+
+protected:
+       void run();
+
+
+private:
+       bool loaded;
+       QString m_file;
+       QPluginLoader *m_pluginLoader;
+       LauncherPluginBase *m_plugin;
+       QSemaphore m_waitStarted;
+};
+
+#endif // PLUGINTHREAD_H
diff --git a/launcher/qml/Components/ResultDelegate.qml b/launcher/qml/Components/ResultDelegate.qml
new file mode 100644 (file)
index 0000000..c8b4c35
--- /dev/null
@@ -0,0 +1,103 @@
+import QtQuick 1.0
+
+Component {
+       Item {
+               id: wrapper
+
+               property bool open: false
+
+               height: 50
+               width: listView.width - 10
+               anchors.horizontalCenter: parent.horizontalCenter
+
+               MouseArea {
+                       id: mouseArea
+                       hoverEnabled: true
+                       anchors.fill: parent
+
+                       onClicked: {
+                               resultModel.selectedIndex = index
+                               mainWindow.handleReturn()
+                       }
+               }
+
+               Rectangle {
+                       id: bg
+                       x: 2
+                       y: 2
+
+                       width: parent.width - 2 * x
+                       height: parent.height - 2 * y
+
+                       radius: 10
+
+                       border.width: resultModel.selectedIndex == index || mouseArea.containsMouse ? 2 : 0
+                       border.color: resultModel.selectedIndex == index ? "red" : mouseArea.containsMouse ? "yellow" : "#000000"
+                       opacity: 0.90
+                       color: isCurrent ? "steelblue" : "grey"
+
+                       Item {
+                               anchors.leftMargin: 10
+                               anchors.rightMargin: 10
+                               anchors.fill: parent
+
+                               Text {
+                                       id: pluginNameText
+                                       font.italic: true
+                                       text: pluginName
+                                       anchors.right: parent.right
+                               }
+
+                               Text {
+                                       id: resultMatchText
+                                       anchors.centerIn: parent
+                                       text: resultMatch
+                               }
+
+                               Text {
+                                       id: resultDescritpionText
+                                       anchors.bottom: parent.bottom
+                                       anchors.left: parent.left
+                                       anchors.right: parent.right
+                                       elide: Text.ElideRight
+                                       text: resultDescription
+                               }
+                       }
+               }
+               states: [
+                       State {
+                               when: mainWindow.selectedIndex == index
+                               PropertyChanges {
+                                       target: wrapper
+                                       height: 100
+                               }
+                       }
+               ]
+
+               transitions: [
+                       Transition {
+                               PropertyAnimation {
+                                       properties: "x,y,height,width,opacity"; easing.type: Easing.InOutQuad; duration: 300
+                               }
+                       }
+               ]
+
+               ListView.onAdd: SequentialAnimation {
+                       PropertyAction { target: wrapper; property: "opacity"; value: 0 }
+                       PropertyAction { target: wrapper; property: "height"; value: 0 }
+                       ParallelAnimation {
+                               NumberAnimation { target: wrapper; property: "height"; to: 50; duration: 500; easing.type: Easing.InOutQuad }
+                               NumberAnimation { target: wrapper; property: "opacity"; to: 1; duration: 500; easing.type: Easing.InOutQuad }
+                       }
+               }
+
+               ListView.onRemove: SequentialAnimation {
+                       PropertyAction { target: wrapper; property: "ListView.delayRemove"; value: true }
+                       ParallelAnimation {
+                               NumberAnimation { target: wrapper; property: "height"; to: 0; duration: 500; easing.type: Easing.InOutQuad }
+                               NumberAnimation { target: wrapper; property: "opacity"; to: 0; duration: 500; easing.type: Easing.InOutQuad }
+                       }
+                       PropertyAction { target: wrapper; property: "ListView.delayRemove"; value: false }
+               }
+       }
+}
diff --git a/launcher/qml/view.qml b/launcher/qml/view.qml
new file mode 100644 (file)
index 0000000..1888735
--- /dev/null
@@ -0,0 +1,31 @@
+import QtQuick 1.0
+import "Components" 1.0 as Components
+
+Item {
+       id: main
+
+       signal resultSelected
+
+//     opacity: 0.1
+
+       ListModel {
+               id: dummyModel
+               ListElement
+               {
+                       pluginName: "foo"
+                       resultMatch: "foo"
+               }
+       }
+
+       ListView {
+               id: listView
+
+               anchors.fill: parent
+               model: resultModel
+               delegate: Components.ResultDelegate {}
+               footer: Item {
+                       width: listView.width
+                       height: listView.height / 2
+               }
+       }
+}
diff --git a/launcher/resources.qrc b/launcher/resources.qrc
new file mode 100644 (file)
index 0000000..3b0fd8c
--- /dev/null
@@ -0,0 +1,7 @@
+<RCC>
+    <qresource prefix="/">
+        <file>icon.png</file>
+        <file>qml/view.qml</file>
+        <file>qml/Components/ResultDelegate.qml</file>
+    </qresource>
+</RCC>
diff --git a/launcher/resultmodel.cpp b/launcher/resultmodel.cpp
new file mode 100644 (file)
index 0000000..3b19689
--- /dev/null
@@ -0,0 +1,230 @@
+#include "resultmodel.h"
+
+#include "plugin.h"
+#include "launcherpluginbase.h"
+
+#include <QDebug>
+
+ResultModel::ResultModel(QObject *parent) :
+       QAbstractListModel(parent), rowCountDelta(0), emptyCommand(true)
+{
+       QHash<int, QByteArray> roles;
+       roles[PluginName]                       = "pluginName";
+       roles[ResultMatch]                      = "resultMatch";
+       roles[ResultDescription]        = "resultDescription";
+       roles[ResultCommand]            = "resultCommand";
+       roles[IsCurrent]                        = "isCurrent";
+       setRoleNames(roles);
+}
+
+ResultModel::~ResultModel()
+{
+       qDeleteAll(results);
+}
+
+int ResultModel::selectedIndex() const
+{
+       return m_selectedIndex;
+}
+
+Result ResultModel::selectedResult() const
+{
+       qDebug() << "selectedResult" << m_selectedIndex;
+       if (m_selectedIndex > rowCount())
+               return Result();
+
+       return results[m_selectedIndex]->result;
+}
+
+void ResultModel::setSelectedIndex(int idx)
+{
+       if (!rowCount() || idx >= rowCount())
+               idx = 0;
+       if (idx < 0)
+               idx = rowCount() - 1;
+
+       if (m_selectedIndex != idx)
+       {
+               m_selectedIndex = idx;
+               emit selectedIndexChanged(idx);
+       }
+}
+
+void ResultModel::clear()
+{
+       beginRemoveRows(QModelIndex(), 0, rowCount());
+       pluginOrder.clear();
+       qDeleteAll(results);
+       results.clear();
+       endRemoveRows();
+}
+
+QVariant ResultModel::data(const QModelIndex &index, int role) const
+{
+       if (index.row() < 0)
+               return QVariant("negative index");
+
+       PluginResult *pluginResult = results[index.row()];
+       switch (role)
+       {
+               case Qt::DisplayRole:
+               case PluginName:
+                       return pluginResult->plugin->pluginInstance()->name();
+               break;
+               case ResultMatch:
+                       return pluginResult->result.match;
+               case ResultDescription:
+                       return pluginResult->result.description;
+               break;
+               case ResultCommand:
+                       return pluginResult->result.command;
+               break;
+               case IsCurrent:
+                       return pluginResult->isCurrent;
+               break;
+               default:
+                       return QVariant();
+               break;
+       }
+       return QVariant();
+}
+
+int ResultModel::rowCount(const QModelIndex &) const
+{
+       return results.count();
+}
+
+void ResultModel::commandChanged(const QString &cmd)
+{
+       emptyCommand = cmd.isEmpty();
+
+       if (emptyCommand)
+       {
+               clear();
+               return;
+       }
+
+       for (int i = 0; i < results.count(); ++i)
+               results[i]->isCurrent = false;
+
+       emit dataChanged(index(0, 0), index(rowCount() - 1, 0));
+}
+
+void ResultModel::updateResults()
+{
+       if (emptyCommand)
+               return;
+
+       int oldCount = rowCount();
+
+       Plugin *plugin = qobject_cast<Plugin*>(sender());
+       int idx = pluginOrder.indexOf(plugin);
+
+       if (idx == -1)
+       {
+               if (!plugin->latestResult().results.count())
+                       return;
+               pluginOrder << plugin;
+       }
+
+       beginResetModel();
+
+       qDeleteAll(results);
+       results.clear();
+
+       for (int i = 0; i < pluginOrder.count(); ++i)
+       {
+               Plugin *p = pluginOrder[i];
+
+               for (int j = 0; j < p->latestResult().results.count(); ++j)
+               {
+                       Result r = p->latestResult().results[j];
+                       PluginResult *pr = new PluginResult;
+                       pr->isCurrent = true;
+                       pr->plugin = p;
+                       pr->result = r;
+                       results << pr;
+               }
+       }
+       endResetModel();
+
+/*     Plugin *plugin = qobject_cast<Plugin*>(sender());
+       auto it = pluginOrder.find(plugin);
+       int pluginIdx;
+       int resultIdx;
+       int oldResultCount;
+       int newResultCount;
+
+       if (it == resultMap.end())
+       {
+               if (!plugin->latestResult().results.count())
+                       return;
+
+               pluginOrder.append(plugin);
+
+               pluginIdx = pluginOrder.count();
+
+               PluginResult *pr = new PluginResult;
+               pr->plugin = plugin;
+
+               results.append(pr);
+               resultMap.insert(plugin, pr);
+
+               pluginIdx = results.count() - 1;
+               resultIdx = rowCount();
+               oldResultCount = 0;
+       }
+
+       if (it != resultMap.end())
+       {
+               pluginIdx = results.indexOf(it.value());
+               resultIdx = 0;
+               for (int i = 0; i < pluginIdx; ++i)
+                       resultIdx += results[i]->count();
+
+               oldResultCount = plugin->previousResult().results.count();
+       }
+
+       newResultCount = plugin->latestResult().results.count();
+
+       results[pluginIdx]->isCurrent = plugin->isCurrentResult();
+
+       if (oldResultCount == newResultCount)
+       {
+qDebug() << "Updating rows" << newResultCount;
+
+               if (newResultCount)
+                       updateResultsForRange(resultIdx, newResultCount);
+       }
+       else if(oldResultCount < newResultCount)
+       {
+qDebug() << "Adding rows";
+               if (oldResultCount)
+                       updateResultsForRange(resultIdx, oldResultCount);
+//             rowCountDelta = -(newResultCount - oldResultCount);
+               beginInsertRows(QModelIndex(), resultIdx + oldResultCount, resultIdx + newResultCount - 1);
+               rowCountDelta = 0;
+               endInsertRows();
+       }
+       else
+       {
+qDebug() << "Removing rows";
+//             rowCountDelta = oldResultCount - newResultCount;
+               beginRemoveRows(QModelIndex(), resultIdx + newResultCount, resultIdx + oldResultCount - 1);
+               rowCountDelta = 0;
+               endRemoveRows();
+               if (newResultCount)
+                       updateResultsForRange(resultIdx, newResultCount);
+       }
+*/
+       if (oldCount != rowCount())
+               setSelectedIndex(0);
+}
+
+void ResultModel::updateResultsForRange(int start, int end)
+{
+qDebug() << "Data changed" << start << (start+end-1);
+       QModelIndex sidx = index(start, 0);
+       QModelIndex eidx = index(start + end - 1, 0);
+       emit dataChanged(sidx, eidx);
+}
diff --git a/launcher/resultmodel.h b/launcher/resultmodel.h
new file mode 100644 (file)
index 0000000..00a2639
--- /dev/null
@@ -0,0 +1,62 @@
+#ifndef RESULTMODEL_H
+#define RESULTMODEL_H
+
+#include <QAbstractListModel>
+#include "reply.h"
+
+class Plugin;
+
+class ResultModel : public QAbstractListModel
+{
+       Q_OBJECT
+       Q_PROPERTY(int selectedIndex READ selectedIndex WRITE setSelectedIndex NOTIFY selectedIndexChanged())
+public:
+       struct PluginResult {
+               bool isCurrent;
+               Plugin *plugin;
+               Result result;
+       };
+
+       enum Roles
+       {
+               PluginName = Qt::UserRole + 1,
+               ResultMatch,
+               ResultDescription,
+               ResultCommand,
+               IsCurrent
+       };
+
+       explicit ResultModel(QObject *parent = 0);
+       ~ResultModel();
+
+       QVariant data(const QModelIndex &index, int role) const;
+
+       int rowCount(const QModelIndex & = QModelIndex()) const;
+       
+       int selectedIndex() const;
+       Result selectedResult() const;
+
+public slots:
+       void commandChanged(const QString &cmd);
+       void updateResults();
+
+       void setSelectedIndex(int idx);
+
+       void clear();
+
+signals:
+       void selectedIndexChanged(int idx);
+
+private:
+       void updateResultsForRange(int start, int end);
+
+       QList<Plugin*> pluginOrder;
+       QList<PluginResult*> results;
+       int rowCountDelta;
+
+       int m_selectedIndex;
+
+       bool emptyCommand;
+};
+
+#endif // RESULTMODEL_H
diff --git a/launcher/tray.cpp b/launcher/tray.cpp
new file mode 100644 (file)
index 0000000..cff1444
--- /dev/null
@@ -0,0 +1,8 @@
+#include "tray.h"
+
+#include <QMenu>
+
+Tray::Tray(QObject *parent) :
+       QSystemTrayIcon(parent)
+{
+}
diff --git a/launcher/tray.h b/launcher/tray.h
new file mode 100644 (file)
index 0000000..a261203
--- /dev/null
@@ -0,0 +1,18 @@
+#ifndef TRAY_H
+#define TRAY_H
+
+#include <QSystemTrayIcon>
+
+class Tray : public QSystemTrayIcon
+{
+       Q_OBJECT
+public:
+       explicit Tray(QObject *parent = 0);
+       
+signals:
+       
+public slots:
+       
+};
+
+#endif // TRAY_H
diff --git a/pluginapi/launcherpluginbase.cpp b/pluginapi/launcherpluginbase.cpp
new file mode 100644 (file)
index 0000000..3b86aba
--- /dev/null
@@ -0,0 +1,35 @@
+#include "launcherpluginbase.h"
+
+LauncherPluginBase::LauncherPluginBase(QObject *parent) :
+       QObject(parent)
+{
+}
+
+LauncherPluginBase *LauncherPluginBase::plugin()
+{
+       return this;
+}
+
+QStringList LauncherPluginBase::supportedPrefixes() const
+{
+       return QStringList();
+}
+
+bool LauncherPluginBase::handleNonPrefixedCommands() const
+{
+       return true;
+}
+
+bool LauncherPluginBase::init()
+{
+       return true;
+}
+
+void LauncherPluginBase::deinit()
+{
+}
+
+void LauncherPluginBase::processCommand(const QString &cmd)
+{
+       handleCommand(cmd);
+}
diff --git a/pluginapi/launcherpluginbase.h b/pluginapi/launcherpluginbase.h
new file mode 100644 (file)
index 0000000..52a60f6
--- /dev/null
@@ -0,0 +1,36 @@
+#ifndef LOADERPLUGINBASE_H
+#define LOADERPLUGINBASE_H
+
+#include "pluginapi_global.h"
+#include <QObject>
+#include "launcherplugininterface.h"
+
+#include "reply.h"
+
+class PLUGINAPISHARED_EXPORT LauncherPluginBase : public QObject, public LauncherPluginInterface
+{
+       Q_OBJECT
+       Q_INTERFACES(LauncherPluginInterface)
+public:
+       explicit LauncherPluginBase(QObject *parent = 0);
+       
+
+       LauncherPluginBase *plugin();
+
+       QStringList supportedPrefixes() const;
+       bool handleNonPrefixedCommands() const;
+
+       bool init();
+       void deinit();
+
+       virtual void handleCommand(const QString &cmd) = 0;
+
+public slots:
+       void processCommand(const QString &cmd);
+
+signals:
+       void replyReady(const Reply &match);
+       
+};
+
+#endif // LOADERPLUGINBASE_H
diff --git a/pluginapi/launcherplugininterface.h b/pluginapi/launcherplugininterface.h
new file mode 100644 (file)
index 0000000..356d7bb
--- /dev/null
@@ -0,0 +1,27 @@
+#ifndef LAUNCHERPLUGIN_H
+#define LAUNCHERPLUGIN_H
+
+#include "pluginapi_global.h"
+#include <QStringList>
+
+class LauncherPluginBase;
+
+class PLUGINAPISHARED_EXPORT LauncherPluginInterface
+{
+public:
+       virtual ~LauncherPluginInterface() {}
+
+       virtual LauncherPluginBase *plugin() = 0;
+
+       virtual QString name() const = 0;
+
+       virtual QStringList supportedPrefixes() const = 0;
+       virtual bool handleNonPrefixedCommands() const = 0;
+
+       virtual bool init() = 0;
+       virtual void deinit() = 0;
+};
+
+Q_DECLARE_INTERFACE(LauncherPluginInterface, "org.aptx.launcher.pluginapi/1.0")
+
+#endif // LAUNCHERPLUGIN_H
diff --git a/pluginapi/loaderplugin.cpp b/pluginapi/loaderplugin.cpp
new file mode 100644 (file)
index 0000000..63b2ce1
--- /dev/null
@@ -0,0 +1,6 @@
+#include "loaderplugin.h"
+
+
+LoaderPluginInterface::LoaderPluginInterface()
+{
+}
diff --git a/pluginapi/pluginapi.pri b/pluginapi/pluginapi.pri
new file mode 100644 (file)
index 0000000..98eac58
--- /dev/null
@@ -0,0 +1,4 @@
+INCLUDEPATH += $$PWD
+DEPENDPATH += $$PWD
+LIBS += -lpluginapi
+LIBS += -L$$PWD/../build
diff --git a/pluginapi/pluginapi.pro b/pluginapi/pluginapi.pro
new file mode 100644 (file)
index 0000000..d4d1332
--- /dev/null
@@ -0,0 +1,18 @@
+QT -= gui
+
+DESTDIR = ../build
+TARGET = pluginapi
+TEMPLATE = lib
+
+DEFINES += PLUGINAPI_LIBRARY
+
+HEADERS += launcherplugininterface.h \
+       pluginapi_global.h \
+       launcherpluginbase.h \
+       reply.h
+
+
+
+SOURCES += \
+       launcherpluginbase.cpp \
+       reply.cpp
diff --git a/pluginapi/pluginapi_global.h b/pluginapi/pluginapi_global.h
new file mode 100644 (file)
index 0000000..23ccb8c
--- /dev/null
@@ -0,0 +1,12 @@
+#ifndef PLUGINAPI_GLOBAL_H
+#define PLUGINAPI_GLOBAL_H
+
+#include <QtCore/qglobal.h>
+
+#if defined(PLUGINAPI_LIBRARY)
+#  define PLUGINAPISHARED_EXPORT Q_DECL_EXPORT
+#else
+#  define PLUGINAPISHARED_EXPORT Q_DECL_IMPORT
+#endif
+
+#endif // PLUGINAPI_GLOBAL_H
diff --git a/pluginapi/reply.cpp b/pluginapi/reply.cpp
new file mode 100644 (file)
index 0000000..1215555
--- /dev/null
@@ -0,0 +1,25 @@
+#include "reply.h"
+
+Result::Result()
+{
+       commandType = RunCommand;
+}
+
+Result::Result(const QString &match_, const QString &description_, CommandType commandType_,
+                          const QString &command_, const QStringList &args_) :
+       match(match_), description(description_), commandType(commandType_),
+       command(command_), args(args_)
+{
+}
+
+Reply::Reply(const QVector<Result> &results_) :
+       results(results_)
+{
+}
+
+void Reply::addResult(const Result &result)
+{
+       results.append(result);
+}
+
+
diff --git a/pluginapi/reply.h b/pluginapi/reply.h
new file mode 100644 (file)
index 0000000..dc924c0
--- /dev/null
@@ -0,0 +1,37 @@
+#ifndef REPLY_H
+#define REPLY_H
+
+#include "pluginapi_global.h"
+#include <QMetaType>
+#include <QVector>
+#include <QStringList>
+
+enum CommandType {
+       RunCommand,
+       OpenCommand
+};
+
+struct PLUGINAPISHARED_EXPORT Result {
+       QString match;
+       QString description;
+
+       CommandType commandType;
+       QString command;
+       QStringList args;
+
+       explicit Result();
+       Result(const QString &match_, const QString &description_ = QString(),
+                  CommandType commandType_ = RunCommand, const QString &command_ = QString(), const QStringList &args_ = QStringList());
+};
+
+struct PLUGINAPISHARED_EXPORT Reply {
+       QVector<Result> results;
+
+       Reply(const QVector<Result> &results_ = QVector<Result>());
+       void addResult(const Result &result);
+};
+
+Q_DECLARE_METATYPE(Reply)
+Q_DECLARE_METATYPE(Reply*)
+
+#endif // MATCH_H
diff --git a/plugins/localmylist/localmylist.pro b/plugins/localmylist/localmylist.pro
new file mode 100644 (file)
index 0000000..ac0be1e
--- /dev/null
@@ -0,0 +1,18 @@
+QT -= gui
+QT += sql
+
+DESTDIR = ../../build
+CONFIG += plugin
+TARGET = localmylist_plugin
+TEMPLATE = lib
+
+DEFINES += LOCALMYLISTPLUGIN_LIBRARY
+
+SOURCES += localmylistplugin.cpp
+
+HEADERS += localmylistplugin.h\
+               localmylistplugin_global.h
+
+include(../../pluginapi/pluginapi.pri)
+
+LIBS += -llocalmylist
diff --git a/plugins/localmylist/localmylistplugin.cpp b/plugins/localmylist/localmylistplugin.cpp
new file mode 100644 (file)
index 0000000..d2aed82
--- /dev/null
@@ -0,0 +1,93 @@
+#include "localmylistplugin.h"
+
+#include <LocalMyList/MyList>
+
+#include <QDebug>
+
+using namespace LocalMyList;
+
+LocalMyListPlugin::LocalMyListPlugin(QObject *parent) : LauncherPluginBase(parent)
+{
+}
+
+bool LocalMyListPlugin::init()
+{
+       MyList::MANUAL_CLEANUP = true;
+
+       LocalMyList::instance()->loadLocalSettings();
+       if (!LocalMyList::instance()->database()->connect())
+       {
+               qDebug() << "Could not connect to database.";
+               return false;
+       }
+       return true;
+}
+
+void LocalMyListPlugin::deinit()
+{
+       MyList::destroy();
+}
+
+QString LocalMyListPlugin::name() const
+{
+       return "LocalMyList";
+}
+
+void LocalMyListPlugin::handleCommand(const QString &cmd)
+{
+       Reply re;
+
+       QSqlQuery &q = LocalMyList::instance()->database()->prepare(
+       "SELECT DISTINCT a.aid, b.title AS MainTitle, a.title AS searchTitle FROM anime_title a"
+       "       LEFT JOIN anime_title b on b.aid = a.aid "
+//     "       LEFT JOIN episode e ON e.aid = a.aid "
+//     "       LEFT JOIN file f ON f.aid = a.aid "
+//     "       LEFT JOIN file_location fl ON fl.fid = f.fid "
+       "       WHERE lower(a.title) LIKE :title "
+       "               AND b.type = 1 "
+       "       ORDER BY a.title ASC, a.aid ASC "
+       );
+
+       q.bindValue(":title", cmd);
+       if (!LocalMyList::instance()->database()->exec(q))
+       {
+               emit replyReady(re);
+               return;
+       }
+       addResults(re, q);
+
+       q.bindValue(":title", cmd + "%");
+       if (!LocalMyList::instance()->database()->exec(q))
+       {
+               emit replyReady(re);
+               return;
+       }
+       addResults(re, q);
+
+       q.bindValue(":title", "%" + cmd + "%");
+       if (!LocalMyList::instance()->database()->exec(q))
+       {
+               emit replyReady(re);
+               return;
+       }
+       addResults(re, q);
+
+       emit replyReady(re);
+}
+
+void LocalMyListPlugin::addResults(Reply &re, QSqlQuery &q)
+{
+       while(q.next())
+       {
+               Result r;
+               r.match = q.value(2).toString();
+               r.description = QString("Main title: %1").arg(q.value(1).toString());
+//             r.commandType = OpenCommand;
+//             r.command = ofd.path;
+               re.addResult(r);
+       }
+       q.finish();
+}
+
+#include <QtPlugin>
+Q_EXPORT_PLUGIN2(localmylist_plugin, LocalMyListPlugin)
diff --git a/plugins/localmylist/localmylistplugin.h b/plugins/localmylist/localmylistplugin.h
new file mode 100644 (file)
index 0000000..4bc2b39
--- /dev/null
@@ -0,0 +1,24 @@
+#ifndef LOCALMYLISTPLUGIN_H
+#define LOCALMYLISTPLUGIN_H
+
+#include "localmylistplugin_global.h"
+#include <launcherpluginbase.h>
+
+#include <QSqlQuery>
+
+class LOCALMYLISTPLUGINSHARED_EXPORT LocalMyListPlugin : public LauncherPluginBase
+{
+public:
+       LocalMyListPlugin(QObject *parent = 0);
+
+       bool init();
+       void deinit();
+
+       QString name() const;
+       void handleCommand(const QString &cmd);
+
+private:
+       void addResults(Reply &re, QSqlQuery &q);
+};
+
+#endif // LOCALMYLIST_H
diff --git a/plugins/localmylist/localmylistplugin_global.h b/plugins/localmylist/localmylistplugin_global.h
new file mode 100644 (file)
index 0000000..384c1ed
--- /dev/null
@@ -0,0 +1,12 @@
+#ifndef LOCALMYLISTPLUGIN_GLOBAL_H
+#define LOCALMYLISTPLUGIN_GLOBAL_H
+
+#include <QtCore/qglobal.h>
+
+#if defined(LOCALMYLISTPLUGIN_LIBRARY)
+#  define LOCALMYLISTPLUGINSHARED_EXPORT Q_DECL_EXPORT
+#else
+#  define LOCALMYLISTPLUGINSHARED_EXPORT Q_DECL_IMPORT
+#endif
+
+#endif // LOCALMYLISTPLUGIN_GLOBAL_H
diff --git a/plugins/plugins.pro b/plugins/plugins.pro
new file mode 100644 (file)
index 0000000..2097898
--- /dev/null
@@ -0,0 +1,5 @@
+TEMPLATE = subdirs
+CONFIG += ordered
+
+SUBDIRS += test \
+       localmylist
diff --git a/plugins/test/test.cpp b/plugins/test/test.cpp
new file mode 100644 (file)
index 0000000..e1a5b6f
--- /dev/null
@@ -0,0 +1,35 @@
+#include "test.h"
+
+Test::Test(QObject *parent) : LauncherPluginBase(parent)
+{
+}
+
+QString Test::name() const
+{
+       return "Test";
+}
+
+void Test::handleCommand(const QString &cmd)
+{
+       Reply re;
+       if (cmd.isEmpty())
+       {
+               emit replyReady(re);
+               return;
+       }
+
+       int z=0;
+       for(int i =0; i<100000000;++i) z+=cmd.length();
+
+       Result r(cmd, "Echo for " + cmd + " z=" + QString::number(z), RunCommand, "cmd", QStringList("dir"));
+
+       re.addResult(r);
+       r.match += " 1";
+       re.addResult(r);
+       r.match += " 2";
+       re.addResult(r);
+       emit replyReady(re);
+}
+
+#include <QtPlugin>
+Q_EXPORT_PLUGIN2(test_plugin, Test)
diff --git a/plugins/test/test.h b/plugins/test/test.h
new file mode 100644 (file)
index 0000000..2368856
--- /dev/null
@@ -0,0 +1,17 @@
+#ifndef TEST_H
+#define TEST_H
+
+#include "test_global.h"
+#include <launcherpluginbase.h>
+
+
+class TESTSHARED_EXPORT Test : public LauncherPluginBase
+{
+public:
+       Test(QObject *parent = 0);
+
+       QString name() const;
+       void handleCommand(const QString &cmd);
+};
+
+#endif // TEST_H
diff --git a/plugins/test/test.pro b/plugins/test/test.pro
new file mode 100644 (file)
index 0000000..144986d
--- /dev/null
@@ -0,0 +1,24 @@
+QT       -= gui
+
+DESTDIR = ../../build
+CONFIG += plugin
+TARGET = test_plugin
+TEMPLATE = lib
+
+DEFINES += TEST_LIBRARY
+
+SOURCES += test.cpp
+
+HEADERS += test.h\
+        test_global.h
+
+unix:!symbian {
+    maemo5 {
+        target.path = /opt/usr/lib
+    } else {
+        target.path = /usr/lib
+    }
+    INSTALLS += target
+}
+
+include(../../pluginapi/pluginapi.pri)
diff --git a/plugins/test/test_global.h b/plugins/test/test_global.h
new file mode 100644 (file)
index 0000000..d1f81ca
--- /dev/null
@@ -0,0 +1,12 @@
+#ifndef TEST_GLOBAL_H
+#define TEST_GLOBAL_H
+
+#include <QtCore/qglobal.h>
+
+#if defined(TEST_LIBRARY)
+#  define TESTSHARED_EXPORT Q_DECL_EXPORT
+#else
+#  define TESTSHARED_EXPORT Q_DECL_IMPORT
+#endif
+
+#endif // TEST_GLOBAL_H