Commit 6857be3a authored by Daniel Vrátil's avatar Daniel Vrátil 🤖
Browse files

Add main menu to logviewer main window

Add a main menu with standard KXmlGUIWindow actions, actions to
import and clear and brand new feature: actions to jump to previous
and next conversation (using keyboard shortcuts).

Also moved some code, renamed some slots and in general done some
code clean up.

REVIEW: 107408
parent 7fc4262c
......@@ -30,3 +30,4 @@ target_link_libraries(ktp-log-viewer
install(TARGETS ktp-log-viewer DESTINATION ${BIN_INSTALL_DIR})
install(FILES ktp-log-viewer.desktop DESTINATION ${XDG_APPS_INSTALL_DIR})
install(FILES log-viewer.rc DESTINATION ${DATA_INSTALL_DIR}/ktp-log-viewer/)
\ No newline at end of file
......@@ -33,13 +33,18 @@
#include <KTp/logs-importer.h>
#include <QSortFilterProxyModel>
#include <QMenu>
#include <QWebFrame>
#include <KLineEdit>
#include <KPixmapSequence>
#include <KMessageBox>
#include <KDebug>
#include <KStandardAction>
#include <KMenu>
#include <KApplication>
#include <KAction>
#include <KActionCollection>
#include <KMenuBar>
#include "entity-model.h"
#include "entity-proxy-model.h"
......@@ -48,35 +53,24 @@
Q_DECLARE_METATYPE(QModelIndex)
LogViewer::LogViewer(QWidget *parent) :
QWidget(parent),
LogViewer::LogViewer(const Tp::AccountFactoryPtr &accountFactory, const Tp::ConnectionFactoryPtr &connectionFactory,
const Tp::ChannelFactoryPtr &channelFactory, const Tp::ContactFactoryPtr &contactFactory,
QWidget *parent):
KXmlGuiWindow(parent),
ui(new Ui::LogViewer)
{
ui->setupUi(this);
setWindowIcon(KIcon(QLatin1String("documentation")));
Tp::registerTypes();
Tpl::init();
Tp::AccountFactoryPtr accountFactory = Tp::AccountFactory::create(
QDBusConnection::sessionBus(),
Tp::Features() << Tp::Account::FeatureCore
<< Tp::Account::FeatureProfile);
QWidget *widget = new QWidget(this);
setCentralWidget(widget);
ui->setupUi(widget);
Tp::ConnectionFactoryPtr connectionFactory = Tp::ConnectionFactory::create(
QDBusConnection::sessionBus(),
Tp::Features() << Tp::Connection::FeatureCore
<< Tp::Connection::FeatureSelfContact
<< Tp::Connection::FeatureRoster);
Tp::ContactFactoryPtr contactFactory = Tp::ContactFactory::create(
Tp::Features() << Tp::Contact::FeatureAlias
<< Tp::Contact::FeatureAvatarData
<< Tp::Contact::FeatureSimplePresence
<< Tp::Contact::FeatureCapabilities);
Tp::ChannelFactoryPtr channelFactory = Tp::ChannelFactory::create(QDBusConnection::sessionBus());
setupActions();
setupGUI(Keys | Save | Create, QLatin1String("log-viewer.rc"));
/* Setup AccountManager */
m_accountManager = Tp::AccountManager::create(accountFactory, connectionFactory, channelFactory, contactFactory);
connect(m_accountManager->becomeReady(), SIGNAL(finished(Tp::PendingOperation*)), SLOT(onAccountManagerReady()));
m_entityModel = new EntityModel(this);
m_filterModel = new EntityProxyModel(this);
......@@ -89,29 +83,58 @@ LogViewer::LogViewer(QWidget *parent) :
ui->entityFilter->setProxy(m_filterModel);
ui->entityFilter->lineEdit()->setClickMessage(i18nc("Placeholder text in line edit for filtering contacts", "Filter contacts..."));
connect(m_accountManager->becomeReady(), SIGNAL(finished(Tp::PendingOperation*)), SLOT(onAccountManagerReady()));
connect(ui->entityList->selectionModel(), SIGNAL(currentChanged(QModelIndex,QModelIndex)), SLOT(onEntitySelected(QModelIndex,QModelIndex)));
connect(ui->datePicker, SIGNAL(dateChanged(QDate)), SLOT(onDateSelected()));
connect(ui->messageView, SIGNAL(conversationSwitchRequested(QDate)), SLOT(switchConversation(QDate)));
connect(ui->globalSearch, SIGNAL(returnPressed(QString)), SLOT(startGlobalSearch(QString)));
connect(ui->globalSearch, SIGNAL(clearButtonClicked()), SLOT(clearGlobalSearch()));
connect(ui->entityList, SIGNAL(customContextMenuRequested(QPoint)), SLOT(showEntityListContextMenu(QPoint)));
/* Build the popup menu for entity list */
m_entityListContextMenu = new QMenu(ui->entityList);
m_clearAccountHistoryAction = new QAction(i18n("Clear account history"), m_entityListContextMenu);
connect(m_clearAccountHistoryAction, SIGNAL(triggered(bool)), SLOT(clearAccountHistory()));
m_entityListContextMenu->addAction(m_clearAccountHistoryAction);
m_clearContactHistoryAction = new QAction(i18n("Clear contact history"), m_entityListContextMenu);
connect(m_clearContactHistoryAction, SIGNAL(triggered(bool)), SLOT(clearContactHistory()));
m_entityListContextMenu->addAction(m_clearContactHistoryAction);
connect(ui->messageView, SIGNAL(conversationSwitchRequested(QDate)), SLOT(slotSetConversationDate(QDate)));
connect(ui->globalSearch, SIGNAL(returnPressed(QString)), SLOT(slotStartGlobalSearch(QString)));
connect(ui->globalSearch, SIGNAL(clearButtonClicked()), SLOT(slotClearGlobalSearch()));
connect(ui->entityList, SIGNAL(customContextMenuRequested(QPoint)), SLOT(slotShowEntityListContextMenu(QPoint)));
}
LogViewer::~LogViewer()
{
delete ui;
}
void LogViewer::setupActions()
{
KStandardAction::quit(KApplication::instance(), SLOT(quit()), actionCollection());
KStandardAction::showMenubar(this->menuBar(), SLOT(setVisible(bool)), actionCollection());
KAction *clearAccHistory = new KAction(i18n("Clear &account history"), this);
clearAccHistory->setIcon(KIcon(QLatin1String("edit-clear-history")));
connect(clearAccHistory, SIGNAL(triggered(bool)), SLOT(slotClearAccountHistory()));
KAction *clearContactHistory = new KAction(i18n("Clear &contact history"), this);
clearContactHistory->setIcon(KIcon(QLatin1String("edit-clear-history")));
clearContactHistory->setEnabled(false);
connect(clearContactHistory, SIGNAL(triggered(bool)), SLOT(slotClearContactHistory()));
KAction *importKopeteLogs = new KAction(i18n("&Import Kopete Logs"), this);
importKopeteLogs->setIcon(KIcon(QLatin1String("document-import")));
connect(importKopeteLogs, SIGNAL(triggered(bool)), SLOT(slotImportKopeteLogs()));
KAction *prevConversation = new KAction(i18n("&Previous Conversation"), this);
prevConversation->setShortcut(KShortcut(Qt::CTRL + Qt::Key_P));
prevConversation->setIcon(KIcon(QLatin1String("go-previous")));
prevConversation->setEnabled(false);
connect(prevConversation, SIGNAL(triggered(bool)), SLOT(slotJumpToPrevConversation()));
KAction *nextConversation = new KAction(i18n("&Next Conversation"), this);
nextConversation->setShortcut(KShortcut(Qt::CTRL + Qt::Key_N));
nextConversation->setIcon(KIcon(QLatin1String("go-next")));
nextConversation->setEnabled(false);
connect(nextConversation, SIGNAL(triggered(bool)), SLOT(slotJumpToNextConversation()));
actionCollection()->addAction(QLatin1String("clear-account-logs"), clearAccHistory);
actionCollection()->addAction(QLatin1String("clear-contact-logs"), clearContactHistory);
actionCollection()->addAction(QLatin1String("import-kopete-logs"), importKopeteLogs);
actionCollection()->addAction(QLatin1String("jump-prev-conversation"), prevConversation);
actionCollection()->addAction(QLatin1String("jump-next-conversation"), nextConversation);
/* Build the popup menu for entity list */
m_entityListContextMenu = new KMenu(ui->entityList);
m_entityListContextMenu->addAction(clearAccHistory);
m_entityListContextMenu->addAction(clearContactHistory);
}
void LogViewer::onAccountManagerReady()
......@@ -120,7 +143,8 @@ void LogViewer::onAccountManagerReady()
logManager->setAccountManagerPtr(m_accountManager);
m_entityModel->setAccountManager(m_accountManager);
runKopeteLogsImport();
/* Try to run log import */
slotImportKopeteLogs(false);
}
void LogViewer::onEntitySelected(const QModelIndex &current, const QModelIndex &previous)
......@@ -129,21 +153,26 @@ void LogViewer::onEntitySelected(const QModelIndex &current, const QModelIndex &
/* Ignore account nodes */
if (current.parent() == QModelIndex()) {
actionCollection()->action(QLatin1String("clear-contact-logs"))->setEnabled(false);
return;
}
Tpl::EntityPtr entity = current.data(EntityModel::EntityRole).value<Tpl::EntityPtr>();
Tp::AccountPtr account = current.data(EntityModel::AccountRole).value<Tp::AccountPtr>();
if (!account.isNull() && !entity.isNull()) {
actionCollection()->action(QLatin1String("clear-contact-logs"))->setEnabled(true);
}
ui->datePicker->setEntity(account, entity);
}
void LogViewer::onDateSelected()
{
updateMainView();
slotUpdateMainWindow();
}
void LogViewer::updateMainView()
void LogViewer::slotUpdateMainWindow()
{
QModelIndex currentIndex = ui->entityList->currentIndex();
......@@ -151,8 +180,6 @@ void LogViewer::updateMainView()
return;
}
QPair< QDate, QDate > nearestDates;
/* If the selected date is not within valid (highlighted) dates then display empty
* conversation (even if there is a chat log for that particular date) */
QDate date = ui->datePicker->date();
......@@ -160,8 +187,15 @@ void LogViewer::updateMainView()
date = QDate();
}
nearestDates.first = ui->datePicker->previousDate();
nearestDates.second = ui->datePicker->nextDate();
m_prevConversationDate = ui->datePicker->previousDate();
m_nextConversationDate = ui->datePicker->nextDate();
actionCollection()->action(QLatin1String("jump-prev-conversation"))->setEnabled(m_prevConversationDate.isValid());
actionCollection()->action(QLatin1String("jump-next-conversation"))->setEnabled(m_nextConversationDate.isValid());
QPair< QDate, QDate > nearestDates;
nearestDates.first = m_prevConversationDate;
nearestDates.second = m_nextConversationDate;
Tpl::EntityPtr entity = currentIndex.data(EntityModel::EntityRole).value<Tpl::EntityPtr>();
Tp::ContactPtr contact = currentIndex.data(EntityModel::ContactRole).value<Tp::ContactPtr>();
......@@ -169,12 +203,12 @@ void LogViewer::updateMainView()
ui->messageView->loadLog(account, entity, contact, date, nearestDates);
}
void LogViewer::switchConversation(const QDate &date)
void LogViewer::slotSetConversationDate(const QDate &date)
{
ui->datePicker->setDate(date);
}
void LogViewer::startGlobalSearch(const QString &term)
void LogViewer::slotStartGlobalSearch(const QString &term)
{
if (term.isEmpty()) {
ui->messageView->clearHighlightText();
......@@ -192,10 +226,10 @@ void LogViewer::startGlobalSearch(const QString &term)
Tpl::LogManagerPtr manager = Tpl::LogManager::instance();
Tpl::PendingSearch *search = manager->search(term, Tpl::EventTypeMaskAny);
connect (search, SIGNAL(finished(Tpl::PendingOperation*)),
this, SLOT(globalSearchFinished(Tpl::PendingOperation*)));
this, SLOT(onGlobalSearchFinished(Tpl::PendingOperation*)));
}
void LogViewer::globalSearchFinished(Tpl::PendingOperation *operation)
void LogViewer::onGlobalSearchFinished(Tpl::PendingOperation *operation)
{
Tpl::PendingSearch *search = qobject_cast< Tpl::PendingSearch* >(operation);
Q_ASSERT(search);
......@@ -208,14 +242,14 @@ void LogViewer::globalSearchFinished(Tpl::PendingOperation *operation)
ui->busyAnimation->setVisible(false);
}
void LogViewer::clearGlobalSearch()
void LogViewer::slotClearGlobalSearch()
{
m_filterModel->clearSearchHits();
ui->datePicker->clearSearchHits();
ui->messageView->clearHighlightText();
}
void LogViewer::showEntityListContextMenu (const QPoint &coords)
void LogViewer::slotShowEntityListContextMenu (const QPoint &coords)
{
QModelIndex index = ui->entityList->indexAt(coords);
if (!index.isValid()) {
......@@ -224,21 +258,22 @@ void LogViewer::showEntityListContextMenu (const QPoint &coords)
index = m_filterModel->mapToSource(index);
/* Whether the node is an account or a contact */
if (index.parent() == QModelIndex()) {
m_clearContactHistoryAction->setVisible(false);
m_clearAccountHistoryAction->setVisible(true);
} else {
m_clearContactHistoryAction->setVisible(true);
m_clearAccountHistoryAction->setVisible(false);
}
actionCollection()->action(QLatin1String("clear-contact-logs"))->setEnabled((index.parent() != QModelIndex()));
m_entityListContextMenu->setProperty("index", QVariant::fromValue(index));
m_entityListContextMenu->popup(ui->entityList->mapToGlobal(coords));
}
void LogViewer::clearAccountHistory()
void LogViewer::slotClearAccountHistory()
{
QModelIndex index = m_entityListContextMenu->property("index").value<QModelIndex>();
QModelIndex index = ui->entityList->currentIndex();
/* Usually and account node is selected, so traverse up to it's parent
* account node */
if (index.parent().isValid()) {
index = index.parent();
}
if (!index.isValid()) {
return;
}
......@@ -257,12 +292,12 @@ void LogViewer::clearAccountHistory()
Tpl::LogManagerPtr logManager = Tpl::LogManager::instance();
Tpl::PendingOperation *operation = logManager->clearAccountHistory(account);
connect(operation, SIGNAL(finished(Tpl::PendingOperation*)), SLOT(logClearingFinished(Tpl::PendingOperation*)));
connect(operation, SIGNAL(finished(Tpl::PendingOperation*)), SLOT(onLogClearingFinished(Tpl::PendingOperation*)));
}
void LogViewer::clearContactHistory()
void LogViewer::slotClearContactHistory()
{
QModelIndex index = m_entityListContextMenu->property("index").value<QModelIndex>();
QModelIndex index = ui->entityList->currentIndex();
if (!index.isValid()) {
return;
}
......@@ -283,10 +318,10 @@ void LogViewer::clearContactHistory()
Tpl::LogManagerPtr logManager = Tpl::LogManager::instance();
Tpl::PendingOperation *operation = logManager->clearEntityHistory(account, entity);
connect(operation, SIGNAL(finished(Tpl::PendingOperation*)), SLOT(logClearingFinished(Tpl::PendingOperation*)));
connect(operation, SIGNAL(finished(Tpl::PendingOperation*)), SLOT(onLogClearingFinished(Tpl::PendingOperation*)));
}
void LogViewer::logClearingFinished(Tpl::PendingOperation *operation)
void LogViewer::onLogClearingFinished(Tpl::PendingOperation *operation)
{
if (!operation->errorName().isEmpty() || !operation->errorMessage().isEmpty()) {
/* Make sure we display at least some message */
......@@ -312,13 +347,13 @@ void LogViewer::logClearingFinished(Tpl::PendingOperation *operation)
m_entityListContextMenu->setProperty("index", QVariant());
}
void LogViewer::runKopeteLogsImport()
void LogViewer::slotImportKopeteLogs(bool force)
{
KSharedConfigPtr config = KSharedConfig::openConfig(QLatin1String("ktelepathyrc"));
KConfigGroup logsConfig = config->group("logs");
bool importDone = logsConfig.readEntry(QLatin1String("InitialKopeteImportDone"), QVariant(false)).toBool();
if (importDone) {
if (!force && importDone) {
kDebug() << "Skipping initial Kopete logs import, already done.";
return;
}
......@@ -342,3 +377,21 @@ void LogViewer::runKopeteLogsImport()
logsConfig.writeEntry(QLatin1String("InitialKopeteImportDone"), true);
}
void LogViewer::slotJumpToNextConversation()
{
if (!m_nextConversationDate.isValid()) {
return;
}
ui->datePicker->setDate(m_nextConversationDate);
}
void LogViewer::slotJumpToPrevConversation()
{
if (!m_prevConversationDate.isValid()) {
return;
}
ui->datePicker->setDate(m_prevConversationDate);
}
......@@ -20,11 +20,9 @@
#ifndef LOGVIEWER_H
#define LOGVIEWER_H
#include <QWidget>
#include <TelepathyQt/AccountManager>
#include <KXmlGuiWindow>
#include <TelepathyLoggerQt4/Types>
class QMenu;
namespace Ui {
class LogViewer;
}
......@@ -35,13 +33,16 @@ namespace Tpl {
class EntityModel;
class EntityProxyModel;
class KMenu;
class LogViewer : public QWidget
class LogViewer : public KXmlGuiWindow
{
Q_OBJECT
public:
explicit LogViewer(QWidget *parent = 0);
explicit LogViewer(const Tp::AccountFactoryPtr &accountFactory, const Tp::ConnectionFactoryPtr &connectionFactory,
const Tp::ChannelFactoryPtr &channelFactory, const Tp::ContactFactoryPtr &contactFactory,
QWidget *parent = 0);
~LogViewer();
private Q_SLOTS:
void onAccountManagerReady();
......@@ -49,28 +50,35 @@ private Q_SLOTS:
void onEntitySelected(const QModelIndex &current, const QModelIndex &previous);
void onDateSelected();
void updateMainView();
void switchConversation(const QDate &date);
void slotUpdateMainWindow();
void slotSetConversationDate(const QDate &date);
void startGlobalSearch(const QString &term);
void globalSearchFinished(Tpl::PendingOperation *);
void clearGlobalSearch();
void showEntityListContextMenu(const QPoint &coords);
void slotShowEntityListContextMenu(const QPoint &coords);
void slotClearGlobalSearch();
void slotStartGlobalSearch(const QString &term);
void onGlobalSearchFinished(Tpl::PendingOperation *);
void slotClearAccountHistory();
void slotClearContactHistory();
void onLogClearingFinished(Tpl::PendingOperation *);
void slotImportKopeteLogs(bool force = true);
void slotJumpToPrevConversation();
void slotJumpToNextConversation();
void clearAccountHistory();
void clearContactHistory();
void logClearingFinished(Tpl::PendingOperation *);
private:
void runKopeteLogsImport();
void setupActions();
Ui::LogViewer *ui;
Tp::AccountManagerPtr m_accountManager;
EntityModel *m_entityModel;
EntityProxyModel *m_filterModel;
QMenu *m_entityListContextMenu;
QAction *m_clearAccountHistoryAction;
QAction *m_clearContactHistoryAction;
KMenu *m_entityListContextMenu;
QDate m_prevConversationDate;
QDate m_nextConversationDate;
};
#endif // LOGVIEWER_H
<gui name="ktp-log-viewer"
version="1"
xmlns="http://www.kde.org/standards/kxmlgui/1.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://www.kde.org/standards/kxmlgui/1.0
http://www.kde.org/standards/kxmlgui/1.0/kxmlgui.xsd" >
<MenuBar>
<Menu name="file"/>
<Menu name="logs"><text>L&amp;ogs</text>
<Action name="clear-account-logs"/>
<Action name="clear-contact-logs"/>
<Separator />
<Action name="import-kopete-logs"/>
</Menu>
<Menu name="conversation"><text>&amp;Conversation</text>
<Action name="jump-prev-conversation"/>
<Action name="jump-next-conversation"/>
</Menu>
<Menu name="settings"/>
</MenuBar>
</gui>
......@@ -20,9 +20,13 @@
#include <KUniqueApplication>
#include <KCmdLineArgs>
#include <KAboutData>
#include "log-viewer.h"
#include "version.h"
#include <TelepathyQt/AccountManager>
#include <TelepathyLoggerQt4/Init>
int main(int argc, char *argv[])
{
KAboutData aboutData("ktp-log-viewer",
......@@ -31,7 +35,9 @@ int main(int argc, char *argv[])
KTP_TEXT_UI_VERSION);
aboutData.addAuthor(ki18n("David Edmundson"), ki18n("Developer"), "kde@davidedmundson.co.uk");
aboutData.addAuthor(ki18n("Daniele E. Domenichelli"), ki18n("Developer"), "daniele.domenichelli@gmail.com");
aboutData.addAuthor(ki18n("Dan Vrátil"), ki18n("Developer"), "dvratil@redhat.com");
aboutData.setProductName("telepathy/log-viewer"); //set the correct name for bug reporting
aboutData.setProgramIconName(QLatin1String("documentation"));
aboutData.setLicense(KAboutData::License_GPL_V2);
KCmdLineArgs::init(argc, argv, &aboutData);
......@@ -42,9 +48,32 @@ int main(int argc, char *argv[])
KCmdLineArgs::addCmdLineOptions(options);
KApplication a;
LogViewer w;
w.show();
KApplication app;
Tp::registerTypes();
Tpl::init();
Tp::AccountFactoryPtr accountFactory = Tp::AccountFactory::create(
QDBusConnection::sessionBus(),
Tp::Features() << Tp::Account::FeatureCore
<< Tp::Account::FeatureProfile);
Tp::ConnectionFactoryPtr connectionFactory = Tp::ConnectionFactory::create(
QDBusConnection::sessionBus(),
Tp::Features() << Tp::Connection::FeatureCore
<< Tp::Connection::FeatureSelfContact
<< Tp::Connection::FeatureRoster);
Tp::ContactFactoryPtr contactFactory = Tp::ContactFactory::create(
Tp::Features() << Tp::Contact::FeatureAlias
<< Tp::Contact::FeatureAvatarData
<< Tp::Contact::FeatureSimplePresence
<< Tp::Contact::FeatureCapabilities);
Tp::ChannelFactoryPtr channelFactory = Tp::ChannelFactory::create(QDBusConnection::sessionBus());
LogViewer *logViewer = new LogViewer(accountFactory, connectionFactory, channelFactory, contactFactory);
logViewer->show();
return a.exec();
return app.exec();
}
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment