You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
309 lines
9.8 KiB
309 lines
9.8 KiB
/* |
|
Copyright (c) 2013 Montel Laurent <montel@kde.org> |
|
|
|
This program is free software; you can redistribute it and/or modify it |
|
under the terms of the GNU General Public License, version 2, as |
|
published by the Free Software Foundation. |
|
|
|
This program is distributed in the hope that it will be useful, but |
|
WITHOUT ANY WARRANTY; without even the implied warranty of |
|
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU |
|
General Public License for more details. |
|
|
|
You should have received a copy of the GNU General Public License along |
|
with this program; if not, write to the Free Software Foundation, Inc., |
|
51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA |
|
*/ |
|
|
|
#include "searchdebugwidget.h" |
|
#include "sparqlsyntaxhighlighter.h" |
|
#include "searchdebugnepomukshowdialog.h" |
|
|
|
#include "util.h" |
|
|
|
#include "pimcommon/texteditor/plaintexteditor/plaintexteditorwidget.h" |
|
#include "pimcommon/texteditor/plaintexteditor/plaintexteditor.h" |
|
|
|
|
|
#include <KPIMUtils/ProgressIndicatorLabel> |
|
|
|
#include <akonadi/itemfetchjob.h> |
|
#include <akonadi/itemfetchscope.h> |
|
#include <akonadi/itemsearchjob.h> |
|
|
|
#include <KMessageBox> |
|
#include <KLocale> |
|
|
|
#include <QPlainTextEdit> |
|
#include <QGridLayout> |
|
#include <QVBoxLayout> |
|
#include <QLabel> |
|
#include <QStringListModel> |
|
#include <QPushButton> |
|
#include <QShortcut> |
|
#include <QContextMenuEvent> |
|
#include <QMenu> |
|
#include <QPointer> |
|
|
|
SearchResultListView::SearchResultListView(QWidget *parent) |
|
: QListView(parent) |
|
{ |
|
|
|
} |
|
|
|
SearchResultListView::~SearchResultListView() |
|
{ |
|
|
|
} |
|
|
|
void SearchResultListView::contextMenuEvent( QContextMenuEvent * event ) |
|
{ |
|
const QModelIndex index = indexAt( event->pos() ); |
|
if (!index.isValid()) |
|
return; |
|
|
|
QMenu *popup = new QMenu(this); |
|
QAction *searchNepomukShow = new QAction(i18n("Search with nepomuk show..."), popup); |
|
popup->addAction(searchNepomukShow); |
|
QAction *act = popup->exec( event->globalPos() ); |
|
delete popup; |
|
if (act == searchNepomukShow) { |
|
const QString uid = QLatin1String("akonadi:?item=") + index.data( Qt::DisplayRole ).toString(); |
|
QPointer<SearchDebugNepomukShowDialog> dlg = new SearchDebugNepomukShowDialog(uid, this); |
|
dlg->exec(); |
|
delete dlg; |
|
} |
|
} |
|
|
|
SearchDebugListDelegate::SearchDebugListDelegate( QObject *parent ) |
|
: QStyledItemDelegate ( parent ) |
|
{ |
|
} |
|
|
|
SearchDebugListDelegate::~SearchDebugListDelegate() |
|
{ |
|
} |
|
|
|
QWidget *SearchDebugListDelegate::createEditor( QWidget *, const QStyleOptionViewItem &, const QModelIndex & ) const |
|
{ |
|
return 0; |
|
} |
|
|
|
SearchDebugWidget::SearchDebugWidget(const QString &query, QWidget *parent) |
|
: QWidget(parent) |
|
{ |
|
QGridLayout *layout = new QGridLayout; |
|
|
|
mTextEdit = new PimCommon::PlainTextEditorWidget( this ); |
|
// we install an event filter to catch Ctrl+Return for quick query execution |
|
mTextEdit->installEventFilter( this ); |
|
|
|
indentQuery(query); |
|
new Nepomuk2::SparqlSyntaxHighlighter( mTextEdit->editor()->document() ); |
|
|
|
mResultView = new SearchResultListView; |
|
mResultView->setItemDelegate(new SearchDebugListDelegate(this)); |
|
|
|
mItemView = new PimCommon::PlainTextEditorWidget; |
|
mItemView->setReadOnly(true); |
|
|
|
layout->addWidget( mTextEdit, 0, 0, 1, 2); |
|
layout->addWidget( new QLabel( i18n("Akonadi Id:") ), 1, 0 ); |
|
layout->addWidget( new QLabel( i18n("Messages:") ), 1, 1 ); |
|
|
|
layout->addWidget( mResultView, 2, 0, 1, 1 ); |
|
layout->addWidget( mItemView, 2, 1, 1, 1 ); |
|
|
|
mReduceQuery = new QPushButton( i18n("Reduce query") ); |
|
connect(mReduceQuery, SIGNAL(clicked()), SLOT(slotReduceQuery())); |
|
|
|
mSearchButton = new QPushButton( i18n("Search") ); |
|
mSearchButton->setEnabled(false); |
|
connect( mSearchButton, SIGNAL(clicked()), this, SLOT(slotSearch()) ); |
|
mProgressIndicator = new KPIMUtils::ProgressIndicatorLabel(i18n("Searching...")); |
|
|
|
mResultLabel = new QLabel; |
|
layout->addWidget( mResultLabel, 3, 0, Qt::AlignLeft ); |
|
|
|
layout->addWidget( mProgressIndicator, 4, 0, Qt::AlignLeft ); |
|
layout->addWidget( mSearchButton, 4, 1, Qt::AlignRight ); |
|
layout->addWidget( mReduceQuery, 5, 1, Qt::AlignRight ); |
|
setLayout(layout); |
|
|
|
connect( mResultView, SIGNAL(activated(QModelIndex)), this, SLOT(slotFetchItem(QModelIndex)) ); |
|
connect(mTextEdit->editor(), SIGNAL(textChanged()), SLOT(slotUpdateSearchButton())); |
|
mResultModel = new QStringListModel( this ); |
|
mResultView->setModel( mResultModel ); |
|
|
|
slotSearch(); |
|
} |
|
|
|
SearchDebugWidget::~SearchDebugWidget() |
|
{ |
|
} |
|
|
|
bool SearchDebugWidget::eventFilter( QObject *watched, QEvent *event ) |
|
{ |
|
if( watched == mTextEdit && event->type() == QEvent::KeyPress ) { |
|
QKeyEvent* kev = static_cast<QKeyEvent*>(event); |
|
if( kev->key() == Qt::Key_Return && |
|
kev->modifiers() == Qt::ControlModifier ) { |
|
slotSearch(); |
|
return true; |
|
} |
|
} |
|
|
|
return QWidget::eventFilter( watched, event ); |
|
} |
|
|
|
void SearchDebugWidget::slotUpdateSearchButton() |
|
{ |
|
mSearchButton->setEnabled(!mTextEdit->editor()->toPlainText().isEmpty()); |
|
} |
|
|
|
QString SearchDebugWidget::queryStr() const |
|
{ |
|
return mTextEdit->editor()->toPlainText(); |
|
} |
|
|
|
void SearchDebugWidget::slotSearch() |
|
{ |
|
const QString query = mTextEdit->editor()->toPlainText(); |
|
|
|
if (query.isEmpty()) { |
|
mResultLabel->setText(i18n("Query is empty.")); |
|
mSearchButton->setEnabled(false); |
|
mReduceQuery->setEnabled(false); |
|
return; |
|
} |
|
|
|
mResultModel->setStringList( QStringList() ); |
|
mItemView->editor()->clear(); |
|
mResultLabel->clear(); |
|
mProgressIndicator->start(); |
|
mSearchButton->setEnabled(false); |
|
mReduceQuery->setEnabled(false); |
|
|
|
Akonadi::ItemSearchJob *job = new Akonadi::ItemSearchJob( query ); |
|
connect( job, SIGNAL(result(KJob*)), this, SLOT(slotSearchFinished(KJob*)) ); |
|
} |
|
|
|
void SearchDebugWidget::indentQuery(QString query) |
|
{ |
|
query = query.simplified(); |
|
QString newQuery; |
|
int i = 0; |
|
int indent = 0; |
|
const int space = 4; |
|
|
|
while(i < query.size()) { |
|
newQuery.append(query[i]); |
|
if (query[i] != QLatin1Char('"') && query[i] != QLatin1Char('<') && query[i] != QLatin1Char('\'')) { |
|
if (query[i] == QLatin1Char('{')) { |
|
++indent; |
|
newQuery.append(QLatin1Char('\n')); |
|
newQuery.append(QString().fill(QLatin1Char(' '), indent*space)); |
|
} else if (query[i] == QLatin1Char('.')) { |
|
if(i+2<query.size()) { |
|
if(query[i+1] == QLatin1Char('}')||query[i+2] == QLatin1Char('}')) { |
|
newQuery.append(QLatin1Char('\n')); |
|
newQuery.append(QString().fill(QLatin1Char(' '), (indent-1)*space)); |
|
} else { |
|
newQuery.append(QLatin1Char('\n')); |
|
newQuery.append(QString().fill(QLatin1Char(' '), indent*space)); |
|
} |
|
} else { |
|
newQuery.append(QLatin1Char('\n')); |
|
newQuery.append(QString().fill(QLatin1Char(' '), indent*space)); |
|
} |
|
} else if (query[i] == QLatin1Char('}')) { |
|
indent--; |
|
if (i+2<query.size()) { |
|
if (query[i+2] == QLatin1Char('.')||query[i+1] == QLatin1Char('.')) { |
|
newQuery.append(QString().fill(QLatin1Char(' '), 1)); |
|
} else { |
|
newQuery.append(QLatin1Char('\n')); |
|
newQuery.append(QString().fill(QLatin1Char(' '), indent*space)); |
|
} |
|
} else { |
|
newQuery.append(QLatin1Char('\n')); |
|
newQuery.append(QString().fill(QLatin1Char(' '), indent*space)); |
|
} |
|
} |
|
} else { |
|
++i; |
|
while(i < query.size()) { |
|
if (query[i] == QLatin1Char('"') || query[i] == QLatin1Char('>') || query[i] == QLatin1Char('\'')) { |
|
newQuery.append(query[i]); |
|
break; |
|
} |
|
newQuery.append(query[i]); |
|
++i; |
|
} |
|
} |
|
++i; |
|
} |
|
mTextEdit->editor()->setPlainText( newQuery ); |
|
} |
|
|
|
void SearchDebugWidget::slotReduceQuery() |
|
{ |
|
QString query = mTextEdit->editor()->toPlainText(); |
|
KMail::Util::reduceQuery(query); |
|
indentQuery(query); |
|
} |
|
|
|
void SearchDebugWidget::slotSearchFinished(KJob *job) |
|
{ |
|
mProgressIndicator->stop(); |
|
mSearchButton->setEnabled(true); |
|
mReduceQuery->setEnabled(true); |
|
|
|
if ( job->error() ) { |
|
KMessageBox::error( this, job->errorString() ); |
|
return; |
|
} |
|
|
|
QStringList uidList; |
|
Akonadi::ItemSearchJob *searchJob = qobject_cast<Akonadi::ItemSearchJob*>( job ); |
|
const Akonadi::Item::List items = searchJob->items(); |
|
Q_FOREACH ( const Akonadi::Item &item, items ) { |
|
uidList << QString::number( item.id() ); |
|
} |
|
|
|
mResultModel->setStringList( uidList ); |
|
if (uidList.isEmpty()) { |
|
mResultLabel->setText(i18n("No message found")); |
|
} else { |
|
mResultLabel->setText(i18np("1 message found", "%1 messages found", uidList.count())); |
|
} |
|
} |
|
|
|
void SearchDebugWidget::slotFetchItem( const QModelIndex &index ) |
|
{ |
|
if ( !index.isValid() ) |
|
return; |
|
|
|
const QString uid = index.data( Qt::DisplayRole ).toString(); |
|
Akonadi::ItemFetchJob *fetchJob = new Akonadi::ItemFetchJob( Akonadi::Item( uid.toLongLong() ) ); |
|
fetchJob->fetchScope().fetchFullPayload(); |
|
connect( fetchJob, SIGNAL(result(KJob*)), this, SLOT(slotItemFetched(KJob*)) ); |
|
} |
|
|
|
void SearchDebugWidget::slotItemFetched( KJob *job ) |
|
{ |
|
mItemView->editor()->clear(); |
|
|
|
if ( job->error() ) { |
|
KMessageBox::error( this, i18n("Error on fetching item") ); |
|
return; |
|
} |
|
|
|
Akonadi::ItemFetchJob *fetchJob = qobject_cast<Akonadi::ItemFetchJob*>( job ); |
|
if ( !fetchJob->items().isEmpty() ) { |
|
const Akonadi::Item item = fetchJob->items().first(); |
|
mItemView->editor()->setPlainText( QString::fromUtf8( item.payloadData() ) ); |
|
} |
|
} |
|
|
|
|
|
|