+/**
+ * @file FileFinder/GUI/gui.cpp
+ * @brief GUI for the FileFinder application
+ * @author Enar Vaikene
+ *
+ * Copyright (c) 2011 Enar Vaikene
+ *
+ * This file is part of the eVaf C++ cross-platform application development framework.
+ *
+ * This file can be used under the terms of the GNU General Public License
+ * version 3.0 as published by the Free Software Foundation and appearing in
+ * the file LICENSE included in the packaging of this file. Please review the
+ * the following information to ensure the GNU General Public License version
+ * 3.0 requirements will be met: http://www.gnu.org/copyleft/gpl.html.
+ *
+ * Alternatively, this file may be used in accordance with the Commercial License
+ * Agreement provided with the Software.
+ */
+
+#include "gui.h"
+#include "version.h"
+
+#include "Engine/iFileFinder"
+
+#include <Common/Globals>
+#include <Common/iLogger>
+#include <Common/iRegistry>
+#include <Common/iApp>
+#include <SdiWindow/iSdiWindow>
+
+#include <QtGui>
+
+VER_EXPORT_VERSION_INFO()
+Q_EXPORT_PLUGIN2(VER_MODULE_NAME_STR, eVaf::FileFinder::GUI::Module)
+
+using namespace eVaf;
+
+
+//-------------------------------------------------------------------
+
+void FileFinder::GUI::Internal::MainWidget::keyPressEvent(QKeyEvent * e)
+{
+ if (!e->modifiers() || ((e->modifiers() & Qt::KeypadModifier) && e->key() == Qt::Key_Enter)) {
+ switch (e->key()) {
+ case Qt::Key_Enter:
+ case Qt::Key_Return: {
+ QList<QPushButton *> buttons = qFindChildren<QPushButton *>(this);
+ foreach (QPushButton * btn, buttons) {
+ if (btn->isDefault() && btn->isVisible()) {
+ if (btn->isEnabled())
+ btn->click();
+ return;
+ }
+ }
+ break;
+ }
+ case Qt::Key_Escape:
+ emit quit();
+ break;
+ case Qt::Key_Up:
+ focusPreviousChild();
+ break;
+ case Qt::Key_Down:
+ focusNextChild();
+ break;
+ default:
+ e->ignore();
+ }
+ }
+ else {
+ e->ignore();
+ }
+}
+
+
+//-------------------------------------------------------------------
+
+FileFinder::GUI::Module::Module()
+ : Plugins::iPlugin()
+ , mReady(false)
+ , mFinder(0)
+ , mOpenFileAction(0)
+ , mOpenDirectoryAction(0)
+ , wMain(0)
+ , wDirectory(0)
+ , wRecursive(0)
+ , wIncludeNames(0)
+ , wExcludeNames(0)
+ , wIncludeContent(0)
+ , wExcludeContent(0)
+ , wFind(0)
+{
+ setObjectName(QString("%1.Module").arg(VER_MODULE_NAME_STR));
+
+ EVAF_INFO("%s created", qPrintable(objectName()));
+}
+
+FileFinder::GUI::Module::~Module()
+{
+ EVAF_INFO("%s destroyed", qPrintable(objectName()));
+}
+
+bool FileFinder::GUI::Module::init(QString const & args)
+{
+ Q_UNUSED(args)
+
+ // Get the iFileFinder interface
+ EVAF_TEST_X((mFinder = evafQueryInterface<FileFinder::iFileFinder>("iFileFinder")), "No iFileFinder interface");
+ connect(mFinder, SIGNAL(found(QString,QString)), this, SLOT(found(QString,QString)));
+ connect(mFinder, SIGNAL(finished(bool)), this, SLOT(finished(bool)));
+
+ // Get the main window interface and fill it with widgets
+ SdiWindow::iSdiWindow * win = evafQueryInterface<SdiWindow::iSdiWindow>("iSdiWindow");
+ EVAF_TEST_X(win, "No iSdiWindow interface");
+
+ // Create the main widget for this window
+ wMain = new Internal::MainWidget;
+ connect(wMain, SIGNAL(quit()), qApp, SLOT(quit()));
+ win->addWidget(wMain);
+
+ // Create actions for the window and widgets on it
+ createActions();
+
+ // Create all the other widgets
+ createWidgets();
+
+ // Load stored searches
+ loadHistory();
+
+ mReady = true;
+
+ EVAF_INFO("%s initialized", qPrintable(objectName()));
+
+ return true;
+}
+
+void FileFinder::GUI::Module::done()
+{
+ mReady = false;
+
+ /*
+ * Widgets are deleted by the SdiWindow module. We use wMain to track calls to done() without
+ * proper init().
+ */
+ if (wMain) {
+ wMain = 0;
+ saveHistory();
+ }
+
+ EVAF_INFO("%s finalized", qPrintable(objectName()));
+}
+
+void FileFinder::GUI::Module::saveHistory()
+{
+ QSettings settings(VER_COMPANY_NAME_STR, Common::iApp::instance()->name());
+
+ QStringList t;
+ for (int i = 0; i < wDirectory->count(); ++i)
+ t.append(wDirectory->itemText(i));
+ settings.setValue("FileFinder/Directories", t);
+
+ t.clear();
+ for (int i = 0; i < wIncludeNames->count(); ++i)
+ t.append(wIncludeNames->itemText(i));
+ settings.setValue("FileFinder/IncludeNames", t);
+
+ t.clear();
+ for (int i = 0; i < wExcludeNames->count(); ++i)
+ t.append(wExcludeNames->itemText(i));
+ settings.setValue("FileFinder/ExcludeNames", t);
+
+ t.clear();
+ for (int i = 0; i < wIncludeContent->count(); ++i)
+ t.append(wIncludeContent->itemText(i));
+ settings.setValue("FileFinder/IncludeContent", t);
+
+ t.clear();
+ for (int i = 0; i < wExcludeContent->count(); ++i)
+ t.append(wExcludeContent->itemText(i));
+ settings.setValue("FileFinder/ExcludeContent", t);
+
+}
+
+void FileFinder::GUI::Module::loadHistory()
+{
+ QSettings settings(VER_COMPANY_NAME_STR, Common::iApp::instance()->name());
+
+ wDirectory->addItems(settings.value("FileFinder/Directories").toStringList());
+ wDirectory->setEditText(QDir::currentPath());
+
+ wIncludeNames->addItems(settings.value("FileFinder/IncludeNames").toStringList());
+ wIncludeNames->setEditText("");
+
+ wExcludeNames->addItems(settings.value("FileFinder/ExcludeNames").toStringList());
+ wExcludeNames->setEditText("");
+
+ wIncludeContent->addItems(settings.value("FileFinder/IncludeContent").toStringList());
+ wIncludeContent->setEditText("");
+
+ wExcludeContent->addItems(settings.value("FileFinder/ExcludeContent").toStringList());
+ wExcludeContent->setEditText("");
+}
+
+void FileFinder::GUI::Module::createWidgets()
+{
+ QVBoxLayout * vbox = new QVBoxLayout;
+ wMain->setLayout(vbox);
+
+ QHBoxLayout * hbox = new QHBoxLayout;
+ vbox->addLayout(hbox);
+
+ QLabel * l = new QLabel(tr("&Directory:"));
+ hbox->addWidget(l);
+
+ wDirectory = new QComboBox;
+ wDirectory->setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Preferred);
+ wDirectory->setEditable(true);
+ wDirectory->setInsertPolicy(QComboBox::InsertAtTop);
+ l->setBuddy(wDirectory);
+ hbox->addWidget(wDirectory);
+
+ QPushButton * btn = new QPushButton(tr("&Browse"));
+ connect(btn, SIGNAL(clicked()), this, SLOT(browseDirectory()));
+ hbox->addWidget(btn);
+
+ wRecursive = new QCheckBox(tr("&Recursive"));
+ wRecursive->setChecked(true);
+ hbox->addWidget(wRecursive);
+
+ QGridLayout * gr = new QGridLayout;
+ vbox->addLayout(gr);
+
+ gr->setColumnStretch(1, 1);
+ gr->setColumnStretch(3, 1);
+
+ l = new QLabel(tr("&File filter:"));
+ gr->addWidget(l, 0, 0);
+
+ wIncludeNames = new QComboBox;
+ wIncludeNames->setEditable(true);
+ wIncludeNames->setInsertPolicy(QComboBox::InsertAtTop);
+ l->setBuddy(wIncludeNames);
+ gr->addWidget(wIncludeNames, 0, 1);
+
+ l = new QLabel(tr("¬:"));
+ gr->addWidget(l, 0, 2);
+
+ wExcludeNames = new QComboBox;
+ wExcludeNames->setEditable(true);
+ wExcludeNames->setInsertPolicy(QComboBox::InsertAtTop);
+ l->setBuddy(wExcludeNames);
+ gr->addWidget(wExcludeNames);
+
+ l = new QLabel(tr("C&ontains:"));
+ gr->addWidget(l, 1, 0);
+
+ wIncludeContent = new QComboBox;
+ wIncludeContent->setEditable(true);
+ wIncludeContent->setInsertPolicy(QComboBox::InsertAtTop);
+ l->setBuddy(wIncludeContent);
+ gr->addWidget(wIncludeContent, 1, 1);
+
+ l = new QLabel(tr("no&t:"));
+ gr->addWidget(l, 1, 2);
+
+ wExcludeContent = new QComboBox;
+ wExcludeContent->setEditable(true);
+ wExcludeContent->setInsertPolicy(QComboBox::InsertAtTop);
+ l->setBuddy(wExcludeContent);
+ gr->addWidget(wExcludeContent, 1, 3);
+
+ wResults = new QListWidget;
+ wResults->setContextMenuPolicy(Qt::ActionsContextMenu);
+ wResults->addAction(mOpenFileAction);
+ wResults->addAction(mOpenDirectoryAction);
+ connect(wResults, SIGNAL(currentRowChanged(int)), this, SLOT(currentRowChanged(int)));
+ connect(wResults, SIGNAL(doubleClicked(QModelIndex)), this, SLOT(openFile(QModelIndex)));
+ vbox->addWidget(wResults);
+
+ hbox = new QHBoxLayout;
+ vbox->addLayout(hbox);
+ hbox->addStretch();
+
+ wFind = new QPushButton(tr("&Search"));
+ wFind->setDefault(true);
+ connect(wFind, SIGNAL(clicked()), this, SLOT(find()));
+ hbox->addWidget(wFind);
+
+ btn = new QPushButton(tr("&Close"));
+ connect(btn, SIGNAL(clicked()), qApp, SLOT(quit()));
+ hbox->addWidget(btn);
+}
+
+void FileFinder::GUI::Module::createActions()
+{
+ QAction * a = new QAction(wMain);
+ a->setShortcuts(QKeySequence::Quit);
+ connect(a, SIGNAL(triggered()), qApp, SLOT(quit()));
+ wMain->addAction(a);
+
+ mOpenFileAction = new QAction(tr("&Open"), wMain);
+ mOpenFileAction->setEnabled(false);
+ connect(mOpenFileAction, SIGNAL(triggered()), this, SLOT(openFile()));
+
+ mOpenDirectoryAction = new QAction(tr("Open &location"), wMain);
+ mOpenDirectoryAction->setEnabled(false);
+ connect(mOpenDirectoryAction, SIGNAL(triggered()), this, SLOT(openDirectory()));
+}
+
+void FileFinder::GUI::Module::browseDirectory()
+{
+ QString s = QFileDialog::getExistingDirectory(wMain, tr("Select the directory"), wDirectory->currentText());
+ if (!s.isEmpty())
+ wDirectory->setEditText(s);
+}
+
+void FileFinder::GUI::Module::find()
+{
+ if (!mFinder)
+ return;
+ if (mFinder->busy()) {
+ mFinder->cancel();
+ }
+ else {
+ wResults->clear();
+
+ mFinder->search(wDirectory->currentText(),
+ wRecursive->isChecked(),
+ FileFinder::Filter(
+ wIncludeNames->currentText(),
+ wExcludeNames->currentText(),
+ wIncludeContent->currentText(),
+ wExcludeContent->currentText()
+ )
+ );
+
+ wFind->setText(tr("&Stop"));
+ }
+}
+
+void FileFinder::GUI::Module::found(QString const & file, QString const & dir)
+{
+ QString result = dir;
+ if (!result.endsWith(QChar('/')))
+ result.append(QChar('/'));
+ result.append(file);
+ wResults->addItem(result);
+}
+
+void FileFinder::GUI::Module::finished(bool canceled)
+{
+ Q_UNUSED(canceled)
+
+ wFind->setText(tr("&Search"));
+}
+
+void FileFinder::GUI::Module::currentRowChanged(int currentRow)
+{
+ mOpenFileAction->setEnabled(currentRow >= 0);
+ mOpenDirectoryAction->setEnabled(currentRow >= 0);
+}
+
+void FileFinder::GUI::Module::openFile(QModelIndex const & index)
+{
+ Q_UNUSED(index)
+ if (wResults->currentItem())
+ QDesktopServices::openUrl(QUrl(QString("file:///%1").arg(wResults->currentItem()->text())));
+}
+
+void FileFinder::GUI::Module::openDirectory()
+{
+ if (wResults->currentItem()) {
+ QFileInfo fi(wResults->currentItem()->text());
+ QDesktopServices::openUrl(QUrl(QString("file:///%1").arg(fi.path())));
+ }
+}