/***************************************************************************
* file klflibentryeditor.cpp
* This file is part of the KLatexFormula Project.
* Copyright (C) 2011 by Philippe Faist
* philippe.faist at bluewin.ch
* *
* 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., *
* 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. *
***************************************************************************/
/* $Id$ */
#include <QWidget>
#include <QComboBox>
#include <QLineEdit>
#include <QEvent>
#include <QKeyEvent>
#include <QPixmap>
#include <QApplication>
#include <QClipboard>
#include <klfdisplaylabel.h>
#include <klflatexedit.h>
#include <klfrelativefont.h>
#include "klfconfig.h"
#include "klflib.h"
#include <ui_klflibentryeditor.h>
#include "klflibentryeditor.h"
KLFLibEntryEditor::KLFLibEntryEditor(QWidget *parent)
: QWidget(parent), pInputEnabled(true)
{
u = new Ui::KLFLibEntryEditor;
u->setupUi(this);
setAutoFillBackground(false);
pCurrentStyle = KLFStyle();
KLFRelativeFont *rf = new KLFRelativeFont(this, u->tabsEntry);
/** \bug ###: only on mac? */
rf->setRelPointSize(-2);
rf->setThorough(true);
u->lblPreview->setFixedSize(klfconfig.UI.smallPreviewSize);
u->cbxCategory->setInsertPolicy(QComboBox::InsertAlphabetically);
u->cbxCategory->setDuplicatesEnabled(false);
u->cbxTags->setInsertPolicy(QComboBox::InsertAlphabetically);
u->cbxTags->setDuplicatesEnabled(false);
u->cbxCategory->installEventFilter(this);
u->cbxTags->installEventFilter(this);
u->cbxCategory->addItem("");
u->cbxTags->addItem("");
// do NOT automatically apply changes, rather enable the 'apply changes' button
// connect(u->cbxCategory, SIGNAL(activated(int)), this, SLOT(slotApplyChanges()));
// connect(u->cbxTags, SIGNAL(activated(int)), this, SLOT(slotApplyChanges()));
connect(u->cbxCategory, SIGNAL(activated(int)), this, SLOT(slotModified()));
connect(u->cbxCategory, SIGNAL(editTextChanged(const QString&)), this, SLOT(slotModified()));
connect(u->cbxTags, SIGNAL(activated(int)), this, SLOT(slotModified()));
connect(u->cbxTags, SIGNAL(editTextChanged(const QString&)), this, SLOT(slotModified()));
// preview and latexpreview should be as small as possible (while
// still respecting their minimum sizes...)
u->splitEntryEditor->setSizes(QList<int>() << 100 << 1000);
// setup latex preview / preamble preview text browser
u->txtPreviewLatex->setFont(klfconfig.UI.preambleEditFont);
u->txtStyPreamble->setFont(klfconfig.UI.preambleEditFont);
u->txtStyPreamble->setHeightHintLines(4);
KLF_CONNECT_CONFIG_SH_LATEXEDIT(u->txtPreviewLatex) ;
KLF_CONNECT_CONFIG_SH_LATEXEDIT(u->txtStyPreamble) ;
}
void KLFLibEntryEditor::retranslateUi(bool alsoBaseUi)
{
if (alsoBaseUi)
u->retranslateUi(this);
}
KLFLibEntryEditor::~KLFLibEntryEditor()
{
delete u;
}
bool KLFLibEntryEditor::eventFilter(QObject *object, QEvent *event)
{
if (object == u->cbxCategory || object == u->cbxTags) {
QComboBox *cbx = qobject_cast<QComboBox*>(object);
if (event->type() == QEvent::KeyPress) {
QKeyEvent *ke = (QKeyEvent*) event;
if (ke->key() == Qt::Key_Return || ke->key() == Qt::Key_Enter) {
slotUpdateFromCbx(cbx);
return true;
}
}
}
return QWidget::eventFilter(object, event);
}
void KLFLibEntryEditor::addCategorySuggestions(const QStringList& categorylist)
{
u->cbxCategory->addItems(categorylist);
slotCbxCleanUpCompletions(u->cbxCategory);
}
void KLFLibEntryEditor::displayEntry(const KLFLibEntry& entry)
{
displayEntries(QList<KLFLibEntry>() << entry);
}
void KLFLibEntryEditor::displayEntries(const QList<KLFLibEntry>& entrylist)
{
// refresh the display label's glow effect
/** \bug .... find a better way to synchronize config values like this. ....... */
u->lblPreview->setGlowEffect(klfconfig.UI.glowEffect);
u->lblPreview->setGlowEffectColor(klfconfig.UI.glowEffectColor);
u->lblPreview->setGlowEffectRadius(klfconfig.UI.glowEffectRadius);
u->cbxCategory->lineEdit()->setReadOnly(!pInputEnabled);
u->cbxTags->lineEdit()->setReadOnly(!pInputEnabled);
if (entrylist.size() == 0) {
u->lblPreview->display(QImage(":/pics/nopreview.png"), QImage(), false);
u->txtPreviewLatex->setText(tr("[ No Item Selected ]"));
u->cbxCategory->setEditText(tr("[ No Item Selected ]"));
u->cbxTags->setEditText(tr("[ No Item Selected ]"));
// u->lblStylePreview->setText(tr("[ No Item Selected ]"));
u->cbxCategory->setEnabled(false);
u->cbxTags->setEnabled(false);
u->btnApplyChanges->setEnabled(false);
u->btnRestoreStyle->setEnabled(false);
pCurrentStyle = KLFStyle();
displayStyle(false, KLFStyle());
u->lblStyMathMode->setText(tr("[ No Item Selected ]"));
u->txtStyPreamble->setPlainText(tr("[ No Item Selected ]"));
slotModified(false);
return;
}
if (entrylist.size() == 1) {
KLFLibEntry e = entrylist[0];
QImage img = e.preview();
u->lblPreview->display(img, img, true);
u->txtPreviewLatex->setText(e.latex());
u->cbxCategory->setEditText(e.category());
u->cbxTags->setEditText(e.tags());
pCurrentStyle = e.style();
// u->lblStylePreview->setText(prettyPrintStyle(pCurrentStyle));
u->cbxCategory->setEnabled(true);
u->cbxTags->setEnabled(true);
u->btnApplyChanges->setEnabled(pInputEnabled && true);
u->btnRestoreStyle->setEnabled(true); // NOT pInputEnabled && : not true input
displayStyle(true, pCurrentStyle);
slotModified(false);
return;
}
// multiple items selected
u->lblPreview->display(QImage(":/pics/nopreview.png"), QImage(), false);
u->txtPreviewLatex->setText(tr("[ %n Items Selected ]", 0, entrylist.size()));
u->cbxTags->setEditText(tr("[ Multiple Items Selected ]"));
// if all elements have same category and style, display them, otherwise set
// the respective field empty
QString cat;
bool allsamestyle = true;
KLFStyle style;
int k;
for (k = 0; k < entrylist.size(); ++k) {
QString thiscat = entrylist[k].category();
KLFStyle thisstyle = entrylist[k].style();
if (k == 0) {
cat = thiscat;
style = thisstyle;
allsamestyle = true;
continue;
}
if ( !cat.isEmpty() && thiscat != cat ) {
cat = "";
}
if ( allsamestyle && !(style == thisstyle) ) {
allsamestyle = false;
}
}
u->cbxCategory->setEditText(cat);
if ( allsamestyle ) {
pCurrentStyle = style;
displayStyle(true, pCurrentStyle);
u->btnRestoreStyle->setEnabled(true); // NOT pInputEnabled && : not true input
} else {
pCurrentStyle = KLFStyle();
displayStyle(false, KLFStyle());
u->lblStyMathMode->setText(tr("[ Different Styles ]"));
u->txtStyPreamble->setPlainText(tr("[ Different Styles ]"));
u->btnRestoreStyle->setEnabled(false);
}
u->cbxCategory->setEnabled(pInputEnabled && true);
u->cbxTags->setEnabled(pInputEnabled && false);
u->btnApplyChanges->setEnabled(pInputEnabled && true);
slotModified(false);
}
// private
void KLFLibEntryEditor::displayStyle(bool valid, const KLFStyle& style)
{
if (valid) {
u->lblStyDPI->setText(QString::number(style.dpi));
QPixmap pxfg(16, 16);
pxfg.fill(QColor(style.fg_color));
u->lblStyColFg->setPixmap(pxfg);
if (qAlpha(style.bg_color)) {
QPixmap pxbg(16, 16);
pxbg.fill(QColor(style.bg_color));
u->lblStyColBg->setPixmap(pxbg);
} else {
u->lblStyColBg->setPixmap(QPixmap(":pics/transparenticon16.png"));
}
u->lblStyMathMode->setText(style.mathmode);
u->txtStyPreamble->setPlainText(style.preamble);
if (style.userScript().isEmpty()) {
u->frmUserScript->hide();
} else {
u->frmUserScript->show();
u->lblUserScript->setText(style.userScript);
}
} else {
u->lblStyDPI->setText(QLatin1String("-"));
u->lblStyColFg->setText(QString());
u->lblStyColFg->setPixmap(QPixmap());
u->lblStyColBg->setText(QString());
u->lblStyColBg->setPixmap(QPixmap());
u->lblStyMathMode->setText(QString());
u->txtStyPreamble->setPlainText(QString());
u->frmUserScript->hide();
}
}
void KLFLibEntryEditor::slotCopy()
{
QWidget *fw = QApplication::focusWidget();
if (!isAncestorOf(fw))
return;
if (fw->inherits("QTextEdit")) {
qobject_cast<QTextEdit*>(fw)->copy();
} else if (fw->inherits("QLineEdit")) {
qobject_cast<QLineEdit*>(fw)->copy();
} else if (fw->inherits("QLabel")) {
#if QT_VERSION >= 0x040700
QLabel *lbl = qobject_cast<QLabel*>(fw);
if (lbl->hasSelectedText()) {
QApplication::clipboard()->setText(lbl->selectedText());
}
#endif
}
}
void KLFLibEntryEditor::setInputEnabled(bool enabled)
{
pInputEnabled = enabled;
}
void KLFLibEntryEditor::slotModified(bool modif)
{
pMetaInfoModified = modif;
u->btnApplyChanges->setEnabled(pMetaInfoModified);
}
void KLFLibEntryEditor::slotUpdateFromCbx(QComboBox *cbx)
{
// Apply all changes, this is more natural than applying only the changes
// to the current cbx (and losing the changes to the other)
if (cbx == u->cbxCategory)
// slotApplyChanges(true, false);
slotApplyChanges();
else if (cbx == u->cbxTags)
// slotApplyChanges(false, true);
slotApplyChanges();
else
qWarning("KLFLibEntryEditor::slotUpdateFromCbx: Couldn't find combo box=%p", (void*)cbx);
}
void KLFLibEntryEditor::on_btnApplyChanges_clicked()
{
slotApplyChanges(u->cbxCategory->isEnabled(), u->cbxTags->isEnabled());
}
void KLFLibEntryEditor::slotApplyChanges(bool cat, bool tags)
{
klfDbg("category="<<cat<<" tags="<<tags) ;
QMap<int,QVariant> data;
if (cat && u->cbxCategory->isEnabled()) {
slotCbxSaveCurrentCompletion(u->cbxCategory);
data[KLFLibEntry::Category] = u->cbxCategory->currentText();
}
if (tags && u->cbxTags->isEnabled()) {
slotCbxSaveCurrentCompletion(u->cbxTags);
data[KLFLibEntry::Tags] = u->cbxTags->currentText();
}
klfDbg("data to update: "<<data) ;
if (data.isEmpty())
return;
emit metaInfoChanged(data);
}
void KLFLibEntryEditor::on_btnRestoreStyle_clicked()
{
emit restoreStyle(pCurrentStyle);
}
void KLFLibEntryEditor::slotCbxSaveCurrentCompletion(QComboBox *cbx)
{
cbx->addItem(cbx->currentText());
slotCbxCleanUpCompletions(cbx);
}
void KLFLibEntryEditor::slotCbxCleanUpCompletions(QComboBox *cbx)
{
cbx->blockSignals(true);
QString bkp_edittext = cbx->currentText();
QStringList items;
QStringList uitems;
int k;
for (k = 0; k < cbx->count(); ++k) {
items << cbx->itemText(k);
}
items.sort();
// unique items now
for (k = 0; k < items.size(); ++k) {
if ( ! uitems.contains(items[k]) )
uitems << items[k];
}
// remove all items
while (cbx->count())
cbx->removeItem(0);
cbx->addItems(uitems);
cbx->setEditText(bkp_edittext);
cbx->blockSignals(false);
}