kde-extraapps/gwenview/app/infocontextmanageritem.cpp
Ivailo Monev 39b4708812 gwenview: log debug messages to special area
Signed-off-by: Ivailo Monev <xakepa10@gmail.com>
2023-06-20 04:13:03 +03:00

381 lines
11 KiB
C++

/*
Gwenview: an image viewer
Copyright 2007 Aurélien Gâteau <agateau@kde.org>
This program is free software; you can redistribute it and/or
modify it under the terms of the GNU General Public License
as published by the Free Software Foundation; either version 2
of the License, or (at your option) any later version.
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 "moc_infocontextmanageritem.cpp"
// Qt
#include <QApplication>
#include <QGridLayout>
#include <QtGui/qevent.h>
#include <QLabel>
#include <QPainter>
#include <QPointer>
#include <QPushButton>
#include <QScrollArea>
#include <QTextBrowser>
#include <QToolTip>
#include <QVBoxLayout>
// KDE
#include <KFileItem>
#include <KLocale>
#include <KSqueezedTextLabel>
// Local
#include "imagemetainfodialog.h"
#include "sidebar.h"
#include <lib/contextmanager.h>
#include <lib/eventwatcher.h>
#include <lib/gvdebug.h>
#include <lib/gwenviewconfig.h>
#include <lib/preferredimagemetainfomodel.h>
#include <lib/document/document.h>
#include <lib/document/documentfactory.h>
namespace Gwenview
{
/**
* This widget is capable of showing multiple lines of key/value pairs.
*/
class KeyValueWidget : public QWidget
{
struct Row
{
Row(QWidget* parent)
: keyLabel(new QLabel(parent))
, valueLabel(new QLabel(parent))
{
initLabel(keyLabel);
initLabel(valueLabel);
QPalette pal = keyLabel->palette();
QColor color = pal.color(QPalette::WindowText);
color.setAlphaF(0.65);
pal.setColor(QPalette::WindowText, color);
keyLabel->setPalette(pal);
valueLabel->setContentsMargins(6, 0, 0, 6);
}
~Row()
{
delete keyLabel;
delete valueLabel;
}
int setLabelGeometries(int rowY, int labelWidth)
{
int labelHeight = keyLabel->heightForWidth(labelWidth);
keyLabel->setGeometry(0, rowY, labelWidth, labelHeight);
rowY += labelHeight;
labelHeight = valueLabel->heightForWidth(labelWidth);
valueLabel->setGeometry(0, rowY, labelWidth, labelHeight);
rowY += labelHeight;
return rowY;
}
int heightForWidth(int width) const
{
return keyLabel->heightForWidth(width) + valueLabel->heightForWidth(width);
}
static void initLabel(QLabel* label)
{
label->setWordWrap(true);
label->show();
label->setTextInteractionFlags(Qt::TextSelectableByMouse | Qt::LinksAccessibleByMouse);
}
QLabel* keyLabel;
QLabel* valueLabel;
};
public:
KeyValueWidget(QWidget* parent = 0)
: QWidget(parent)
{
QSizePolicy policy(QSizePolicy::Preferred, QSizePolicy::Fixed);
policy.setHeightForWidth(true);
setSizePolicy(policy);
}
QSize sizeHint() const
{
int width = 150;
int height = heightForWidth(width);
return QSize(width, height);
}
int heightForWidth(int w) const
{
int height = 0;
Q_FOREACH(Row* row, mRows) {
height += row->heightForWidth(w);
}
return height;
}
void clear()
{
qDeleteAll(mRows);
mRows.clear();
updateGeometry();
}
void addRow(const QString& key, const QString& value)
{
Row* row = new Row(this);
row->keyLabel->setText(i18nc(
"@item:intext %1 is a key, we append a colon to it. A value is displayed after",
"%1:", key));
row->valueLabel->setText(value);
mRows << row;
}
static bool rowsLessThan(const Row* row1, const Row* row2)
{
return row1->keyLabel->text() < row2->keyLabel->text();
}
void finishAddRows()
{
qSort(mRows.begin(), mRows.end(), KeyValueWidget::rowsLessThan);
updateGeometry();
}
void layoutRows()
{
// Layout labels manually: I tried to use a QVBoxLayout but for some
// reason when using software animations the widget blinks when going
// from one image to another
int rowY = 0;
const int labelWidth = width();
Q_FOREACH(Row* row, mRows) {
rowY = row->setLabelGeometries(rowY, labelWidth);
}
}
protected:
void showEvent(QShowEvent* event)
{
QWidget::showEvent(event);
layoutRows();
}
void resizeEvent(QResizeEvent* event)
{
QWidget::resizeEvent(event);
layoutRows();
}
private:
QVector<Row*> mRows;
};
struct InfoContextManagerItemPrivate
{
InfoContextManagerItem* q;
SideBarGroup* mGroup;
// One selection fields
QScrollArea* mOneFileWidget;
KeyValueWidget* mKeyValueWidget;
Document::Ptr mDocument;
// Multiple selection fields
QLabel* mMultipleFilesLabel;
QPointer<ImageMetaInfoDialog> mImageMetaInfoDialog;
void updateMetaInfoDialog()
{
if (!mImageMetaInfoDialog) {
return;
}
ImageMetaInfoModel* model = mDocument ? mDocument->metaInfo() : 0;
mImageMetaInfoDialog->setMetaInfo(model, GwenviewConfig::preferredMetaInfoKeyList());
}
void setupGroup()
{
mOneFileWidget = new QScrollArea();
mOneFileWidget->setFrameStyle(QFrame::NoFrame);
mOneFileWidget->setWidgetResizable(true);
mKeyValueWidget = new KeyValueWidget;
QLabel* moreLabel = new QLabel(mOneFileWidget);
moreLabel->setText(QString("<a href='#'>%1</a>").arg(i18nc("@action show more image meta info", "More...")));
moreLabel->setAlignment(Qt::AlignRight);
QWidget* content = new QWidget;
QVBoxLayout* layout = new QVBoxLayout(content);
layout->setMargin(2);
layout->setSpacing(2);
layout->addWidget(mKeyValueWidget);
layout->addWidget(moreLabel);
mOneFileWidget->setWidget(content);
mMultipleFilesLabel = new QLabel();
mGroup = new SideBarGroup(i18nc("@title:group", "Meta Information"));
q->setWidget(mGroup);
mGroup->addWidget(mOneFileWidget);
mGroup->addWidget(mMultipleFilesLabel);
EventWatcher::install(mGroup, QEvent::Show, q, SLOT(updateSideBarContent()));
QObject::connect(moreLabel, SIGNAL(linkActivated(QString)),
q, SLOT(showMetaInfoDialog()));
}
void forgetCurrentDocument()
{
if (mDocument) {
QObject::disconnect(mDocument.data(), 0, q, 0);
// "Garbage collect" document
mDocument = 0;
}
}
};
InfoContextManagerItem::InfoContextManagerItem(ContextManager* manager)
: AbstractContextManagerItem(manager)
, d(new InfoContextManagerItemPrivate)
{
d->q = this;
d->setupGroup();
connect(contextManager(), SIGNAL(selectionChanged()),
SLOT(updateSideBarContent()));
connect(contextManager(), SIGNAL(selectionDataChanged()),
SLOT(updateSideBarContent()));
}
InfoContextManagerItem::~InfoContextManagerItem()
{
delete d;
}
void InfoContextManagerItem::updateSideBarContent()
{
kDebug() << "updateSideBarContent";
if (!d->mGroup->isVisible()) {
kDebug() << "updateSideBarContent: not visible, not updating";
return;
}
kDebug() << "updateSideBarContent: really updating";
KFileItemList itemList = contextManager()->selectedFileItemList();
if (itemList.count() == 0) {
d->forgetCurrentDocument();
d->mOneFileWidget->hide();
d->mMultipleFilesLabel->hide();
d->updateMetaInfoDialog();
return;
}
KFileItem item = itemList.first();
if (itemList.count() == 1 && !item.isDir()) {
fillOneFileGroup(item);
} else {
fillMultipleItemsGroup(itemList);
}
d->updateMetaInfoDialog();
}
void InfoContextManagerItem::fillOneFileGroup(const KFileItem& item)
{
d->mOneFileWidget->show();
d->mMultipleFilesLabel->hide();
d->forgetCurrentDocument();
d->mDocument = DocumentFactory::instance()->load(item.url());
connect(d->mDocument.data(), SIGNAL(metaInfoUpdated()),
SLOT(updateOneFileInfo()));
d->updateMetaInfoDialog();
updateOneFileInfo();
}
void InfoContextManagerItem::fillMultipleItemsGroup(const KFileItemList& itemList)
{
d->forgetCurrentDocument();
int folderCount = 0, fileCount = 0;
Q_FOREACH(const KFileItem & item, itemList) {
if (item.isDir()) {
folderCount++;
} else {
fileCount++;
}
}
if (folderCount == 0) {
d->mMultipleFilesLabel->setText(i18ncp("@label", "%1 file selected", "%1 files selected", fileCount));
} else if (fileCount == 0) {
d->mMultipleFilesLabel->setText(i18ncp("@label", "%1 folder selected", "%1 folders selected", folderCount));
} else {
d->mMultipleFilesLabel->setText(i18nc("@label. The two parameters are strings like '2 folders' and '1 file'.",
"%1 and %2 selected", i18np("%1 folder", "%1 folders", folderCount), i18np("%1 file", "%1 files", fileCount)));
}
d->mOneFileWidget->hide();
d->mMultipleFilesLabel->show();
}
void InfoContextManagerItem::updateOneFileInfo()
{
if (!d->mDocument) {
return;
}
ImageMetaInfoModel* metaInfoModel = d->mDocument->metaInfo();
d->mKeyValueWidget->clear();
Q_FOREACH(const QString & key, GwenviewConfig::preferredMetaInfoKeyList()) {
QString label;
QString value;
metaInfoModel->getInfoForKey(key, &label, &value);
if (!label.isEmpty() && !value.isEmpty()) {
d->mKeyValueWidget->addRow(label, value);
}
}
d->mKeyValueWidget->finishAddRows();
d->mKeyValueWidget->layoutRows();
}
void InfoContextManagerItem::showMetaInfoDialog()
{
if (!d->mImageMetaInfoDialog) {
d->mImageMetaInfoDialog = new ImageMetaInfoDialog(d->mOneFileWidget);
d->mImageMetaInfoDialog->setAttribute(Qt::WA_DeleteOnClose, true);
connect(d->mImageMetaInfoDialog, SIGNAL(preferredMetaInfoKeyListChanged(QStringList)),
SLOT(slotPreferredMetaInfoKeyListChanged(QStringList)));
}
d->mImageMetaInfoDialog->setMetaInfo(d->mDocument ? d->mDocument->metaInfo() : 0, GwenviewConfig::preferredMetaInfoKeyList());
d->mImageMetaInfoDialog->show();
}
void InfoContextManagerItem::slotPreferredMetaInfoKeyListChanged(const QStringList& list)
{
GwenviewConfig::setPreferredMetaInfoKeyList(list);
GwenviewConfig::self()->writeConfig();
updateOneFileInfo();
}
} // namespace