forked from blue/squawk
message context menu began, open and show in folder features
This commit is contained in:
parent
f34289399e
commit
d514db9c4a
@ -46,3 +46,40 @@ QString Shared::processMessageBody(const QString& msg)
|
|||||||
processed.replace(urlReg, "<a href=\"\\1\">\\1</a>");
|
processed.replace(urlReg, "<a href=\"\\1\">\\1</a>");
|
||||||
return "<p style=\"white-space: pre-wrap;\">" + processed + "</p>";
|
return "<p style=\"white-space: pre-wrap;\">" + processed + "</p>";
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static const QStringList query = {"query", "default", "inode/directory"};
|
||||||
|
static const QRegularExpression dolphinReg("[Dd]olphin");
|
||||||
|
static const QRegularExpression nautilusReg("[Nn]autilus");
|
||||||
|
static const QRegularExpression cajaReg("[Cc]aja");
|
||||||
|
static const QRegularExpression nemoReg("[Nn]emo");
|
||||||
|
static const QRegularExpression konquerorReg("kfmclient");
|
||||||
|
|
||||||
|
void Shared::showInDirectory(const QString& path)
|
||||||
|
{
|
||||||
|
QFileInfo info = path;
|
||||||
|
if (info.exists()) {
|
||||||
|
QProcess proc;
|
||||||
|
proc.start("xdg-mime", query);
|
||||||
|
proc.waitForFinished();
|
||||||
|
QString output = proc.readLine().simplified();
|
||||||
|
if (output.contains(dolphinReg)) {
|
||||||
|
proc.startDetached("dolphin", QStringList() << "--select" << info.canonicalFilePath());
|
||||||
|
} else if (output.contains(nautilusReg)) {
|
||||||
|
proc.startDetached("nautilus", QStringList() << "--no-desktop" << info.canonicalFilePath());
|
||||||
|
} else if (output.contains(cajaReg)) {
|
||||||
|
proc.startDetached("caja", QStringList() << "--no-desktop" << info.canonicalFilePath());
|
||||||
|
} else if (output.contains(nemoReg)) {
|
||||||
|
proc.startDetached("nemo", QStringList() << "--no-desktop" << info.canonicalFilePath());
|
||||||
|
} else if (output.contains(konquerorReg)) {
|
||||||
|
proc.startDetached("konqueror", QStringList() << "--select" << info.canonicalFilePath());
|
||||||
|
} else {
|
||||||
|
QString folder;
|
||||||
|
if (info.isDir()) {
|
||||||
|
folder = info.canonicalFilePath();
|
||||||
|
} else {
|
||||||
|
folder = info.canonicalPath();
|
||||||
|
}
|
||||||
|
QDesktopServices::openUrl(QUrl::fromLocalFile(folder));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
@ -20,8 +20,13 @@
|
|||||||
#define SHARED_UTILS_H
|
#define SHARED_UTILS_H
|
||||||
|
|
||||||
#include <QString>
|
#include <QString>
|
||||||
|
#include <QStringList>
|
||||||
#include <QColor>
|
#include <QColor>
|
||||||
#include <QRegularExpression>
|
#include <QRegularExpression>
|
||||||
|
#include <QFileInfo>
|
||||||
|
#include <QProcess>
|
||||||
|
#include <QDesktopServices>
|
||||||
|
#include <QUrl>
|
||||||
|
|
||||||
#include <uuid/uuid.h>
|
#include <uuid/uuid.h>
|
||||||
#include <vector>
|
#include <vector>
|
||||||
@ -30,6 +35,7 @@ namespace Shared {
|
|||||||
|
|
||||||
QString generateUUID();
|
QString generateUUID();
|
||||||
QString processMessageBody(const QString& msg);
|
QString processMessageBody(const QString& msg);
|
||||||
|
void showInDirectory(const QString& path);
|
||||||
|
|
||||||
static const std::vector<QColor> colorPalette = {
|
static const std::vector<QColor> colorPalette = {
|
||||||
QColor(244, 27, 63),
|
QColor(244, 27, 63),
|
||||||
|
@ -379,6 +379,22 @@ void Models::MessageFeed::responseArchive(const std::list<Shared::Message> list,
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
QModelIndex Models::MessageFeed::index(int row, int column, const QModelIndex& parent) const
|
||||||
|
{
|
||||||
|
if (!hasIndex(row, column, parent)) {
|
||||||
|
return QModelIndex();
|
||||||
|
}
|
||||||
|
|
||||||
|
StorageByTime::iterator itr = indexByTime.nth(row);
|
||||||
|
if (itr != indexByTime.end()) {
|
||||||
|
Shared::Message* msg = *itr;
|
||||||
|
|
||||||
|
return createIndex(row, column, msg);
|
||||||
|
} else {
|
||||||
|
return QModelIndex();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
QHash<int, QByteArray> Models::MessageFeed::roleNames() const
|
QHash<int, QByteArray> Models::MessageFeed::roleNames() const
|
||||||
{
|
{
|
||||||
return roles;
|
return roles;
|
||||||
|
@ -61,6 +61,7 @@ public:
|
|||||||
bool canFetchMore(const QModelIndex & parent) const override;
|
bool canFetchMore(const QModelIndex & parent) const override;
|
||||||
void fetchMore(const QModelIndex & parent) override;
|
void fetchMore(const QModelIndex & parent) override;
|
||||||
QHash<int, QByteArray> roleNames() const override;
|
QHash<int, QByteArray> roleNames() const override;
|
||||||
|
QModelIndex index(int row, int column, const QModelIndex & parent) const override;
|
||||||
|
|
||||||
void responseArchive(const std::list<Shared::Message> list, bool last);
|
void responseArchive(const std::list<Shared::Message> list, bool last);
|
||||||
void downloadAttachment(const QString& messageId);
|
void downloadAttachment(const QString& messageId);
|
||||||
|
@ -68,8 +68,13 @@ QModelIndex FeedView::indexAt(const QPoint& point) const
|
|||||||
uint32_t y = vh - point.y() + vo;
|
uint32_t y = vh - point.y() + vo;
|
||||||
|
|
||||||
for (std::deque<Hint>::size_type i = 0; i < hints.size(); ++i) {
|
for (std::deque<Hint>::size_type i = 0; i < hints.size(); ++i) {
|
||||||
if (hints[i].offset + hints[i].height >= y) {
|
const Hint& hint = hints[i];
|
||||||
|
if (y <= hint.offset + hint.height) {
|
||||||
|
if (y > hint.offset) {
|
||||||
return model()->index(i, 0, rootIndex());
|
return model()->index(i, 0, rootIndex());
|
||||||
|
} else {
|
||||||
|
break;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -279,7 +284,8 @@ void FeedView::paintEvent(QPaintEvent* event)
|
|||||||
|
|
||||||
for (const QModelIndex& index : toRener) {
|
for (const QModelIndex& index : toRener) {
|
||||||
option.rect = visualRect(index);
|
option.rect = visualRect(index);
|
||||||
option.state.setFlag(QStyle::State_MouseOver, option.rect.contains(cursor));
|
bool mouseOver = option.rect.contains(cursor) && vp->rect().contains(cursor);
|
||||||
|
option.state.setFlag(QStyle::State_MouseOver, mouseOver);
|
||||||
itemDelegate(index)->paint(&painter, option, index);
|
itemDelegate(index)->paint(&painter, option, index);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -47,7 +47,8 @@ Conversation::Conversation(bool muc, Models::Account* acc, Models::Element* el,
|
|||||||
delegate(new MessageDelegate(this)),
|
delegate(new MessageDelegate(this)),
|
||||||
manualSliderChange(false),
|
manualSliderChange(false),
|
||||||
tsb(QApplication::style()->styleHint(QStyle::SH_ScrollBar_Transient) == 1),
|
tsb(QApplication::style()->styleHint(QStyle::SH_ScrollBar_Transient) == 1),
|
||||||
shadow(10, 1, Qt::black, this)
|
shadow(10, 1, Qt::black, this),
|
||||||
|
contextMenu(new QMenu())
|
||||||
{
|
{
|
||||||
m_ui->setupUi(this);
|
m_ui->setupUi(this);
|
||||||
|
|
||||||
@ -55,6 +56,7 @@ Conversation::Conversation(bool muc, Models::Account* acc, Models::Element* el,
|
|||||||
|
|
||||||
feed->setItemDelegate(delegate);
|
feed->setItemDelegate(delegate);
|
||||||
feed->setFrameShape(QFrame::NoFrame);
|
feed->setFrameShape(QFrame::NoFrame);
|
||||||
|
feed->setContextMenuPolicy(Qt::CustomContextMenu);
|
||||||
delegate->initializeFonts(feed->getFont());
|
delegate->initializeFonts(feed->getFont());
|
||||||
feed->setModel(el->feed);
|
feed->setModel(el->feed);
|
||||||
el->feed->incrementObservers();
|
el->feed->incrementObservers();
|
||||||
@ -62,6 +64,7 @@ Conversation::Conversation(bool muc, Models::Account* acc, Models::Element* el,
|
|||||||
|
|
||||||
connect(el->feed, &Models::MessageFeed::newMessage, this, &Conversation::onFeedMessage);
|
connect(el->feed, &Models::MessageFeed::newMessage, this, &Conversation::onFeedMessage);
|
||||||
connect(feed, &FeedView::resized, this, &Conversation::positionShadow);
|
connect(feed, &FeedView::resized, this, &Conversation::positionShadow);
|
||||||
|
connect(feed, &FeedView::customContextMenuRequested, this, &Conversation::onFeedContext);
|
||||||
|
|
||||||
connect(acc, &Models::Account::childChanged, this, &Conversation::onAccountChanged);
|
connect(acc, &Models::Account::childChanged, this, &Conversation::onAccountChanged);
|
||||||
|
|
||||||
@ -88,8 +91,6 @@ Conversation::Conversation(bool muc, Models::Account* acc, Models::Element* el,
|
|||||||
//m_ui->scrollArea->setBackgroundRole(QPalette::Base);
|
//m_ui->scrollArea->setBackgroundRole(QPalette::Base);
|
||||||
//}
|
//}
|
||||||
|
|
||||||
//m_ui->scrollArea->installEventFilter(&scrollResizeCatcher);
|
|
||||||
|
|
||||||
//line->setMyAvatarPath(acc->getAvatarPath());
|
//line->setMyAvatarPath(acc->getAvatarPath());
|
||||||
//line->setMyName(acc->getName());
|
//line->setMyName(acc->getName());
|
||||||
|
|
||||||
@ -98,6 +99,8 @@ Conversation::Conversation(bool muc, Models::Account* acc, Models::Element* el,
|
|||||||
|
|
||||||
Conversation::~Conversation()
|
Conversation::~Conversation()
|
||||||
{
|
{
|
||||||
|
delete contextMenu;
|
||||||
|
|
||||||
element->feed->decrementObservers();
|
element->feed->decrementObservers();
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -402,3 +405,31 @@ void Conversation::positionShadow()
|
|||||||
shadow.move(feed->pos());
|
shadow.move(feed->pos());
|
||||||
shadow.raise();
|
shadow.raise();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void Conversation::onFeedContext(const QPoint& pos)
|
||||||
|
{
|
||||||
|
QModelIndex index = feed->indexAt(pos);
|
||||||
|
if (index.isValid()) {
|
||||||
|
Shared::Message* item = static_cast<Shared::Message*>(index.internalPointer());
|
||||||
|
|
||||||
|
contextMenu->clear();
|
||||||
|
bool showMenu = false;
|
||||||
|
QString path = item->getAttachPath();
|
||||||
|
if (path.size() > 0) {
|
||||||
|
showMenu = true;
|
||||||
|
QAction* open = contextMenu->addAction(Shared::icon("document-new-from-template"), tr("Open"));
|
||||||
|
connect(open, &QAction::triggered, [path]() {
|
||||||
|
QDesktopServices::openUrl(QUrl::fromLocalFile(path));
|
||||||
|
});
|
||||||
|
|
||||||
|
QAction* show = contextMenu->addAction(Shared::icon("document-new-from-template"), tr("Show in folder"));
|
||||||
|
connect(show, &QAction::triggered, [path]() {
|
||||||
|
Shared::showInDirectory(path);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
if (showMenu) {
|
||||||
|
contextMenu->popup(feed->viewport()->mapToGlobal(pos));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
@ -25,6 +25,9 @@
|
|||||||
#include <QMimeData>
|
#include <QMimeData>
|
||||||
#include <QFileInfo>
|
#include <QFileInfo>
|
||||||
#include <QGraphicsOpacityEffect>
|
#include <QGraphicsOpacityEffect>
|
||||||
|
#include <QMenu>
|
||||||
|
#include <QAction>
|
||||||
|
#include <QDesktopServices>
|
||||||
|
|
||||||
#include "shared/message.h"
|
#include "shared/message.h"
|
||||||
#include "order.h"
|
#include "order.h"
|
||||||
@ -103,6 +106,7 @@ protected slots:
|
|||||||
void onAccountChanged(Models::Item* item, int row, int col);
|
void onAccountChanged(Models::Item* item, int row, int col);
|
||||||
void onFeedMessage(const Shared::Message& msg);
|
void onFeedMessage(const Shared::Message& msg);
|
||||||
void positionShadow();
|
void positionShadow();
|
||||||
|
void onFeedContext(const QPoint &pos);
|
||||||
|
|
||||||
public:
|
public:
|
||||||
const bool isMuc;
|
const bool isMuc;
|
||||||
@ -126,6 +130,7 @@ protected:
|
|||||||
bool tsb; //transient scroll bars
|
bool tsb; //transient scroll bars
|
||||||
|
|
||||||
ShadowOverlay shadow;
|
ShadowOverlay shadow;
|
||||||
|
QMenu* contextMenu;
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif // CONVERSATION_H
|
#endif // CONVERSATION_H
|
||||||
|
Loading…
Reference in New Issue
Block a user