File indexing completed on 2024-05-19 05:05:48

0001 /***************************************************************************
0002  *   SPDX-License-Identifier: GPL-2.0-or-later
0003  *                                                                         *
0004  *   SPDX-FileCopyrightText: 2004-2019 Thomas Fischer <fischer@unix-ag.uni-kl.de>
0005  *                                                                         *
0006  *   This program is free software; you can redistribute it and/or modify  *
0007  *   it under the terms of the GNU General Public License as published by  *
0008  *   the Free Software Foundation; either version 2 of the License, or     *
0009  *   (at your option) any later version.                                   *
0010  *                                                                         *
0011  *   This program is distributed in the hope that it will be useful,       *
0012  *   but WITHOUT ANY WARRANTY; without even the implied warranty of        *
0013  *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the         *
0014  *   GNU General Public License for more details.                          *
0015  *                                                                         *
0016  *   You should have received a copy of the GNU General Public License     *
0017  *   along with this program; if not, see <https://www.gnu.org/licenses/>. *
0018  ***************************************************************************/
0019 
0020 #include "lyx.h"
0021 
0022 #include <QWidget>
0023 #include <QAction>
0024 #include <QDir>
0025 #include <QTextStream>
0026 #include <QFileInfo>
0027 #include <QStandardPaths>
0028 #include <qplatformdefs.h>
0029 
0030 #include <KActionCollection>
0031 #include <KLocalizedString>
0032 #include <KParts/ReadOnlyPart>
0033 #include <KMessageBox>
0034 
0035 #include <Preferences>
0036 
0037 class LyX::LyXPrivate
0038 {
0039 public:
0040     QWidget *widget;
0041     QAction *action;
0042     QStringList references;
0043 
0044     LyXPrivate(LyX *parent, QWidget *widget)
0045             : action(nullptr) {
0046         Q_UNUSED(parent)
0047         this->widget = widget;
0048     }
0049 
0050     QString locateConfiguredLyXPipe() {
0051         QString result;
0052 
0053         /// First, check if automatic detection is disabled.
0054         /// In this case, read the LyX pipe's path from configuration
0055         if (!Preferences::instance().lyXUseAutomaticPipeDetection())
0056             result = Preferences::instance().lyXPipePath();
0057 
0058 #ifdef QT_LSTAT
0059         /// Check if the result so far is empty. This means that
0060         /// either automatic detection is enabled or the path in
0061         /// the configuration is empty/invalid. Proceed with
0062         /// automatic detection in this case.
0063         if (result.isEmpty())
0064             result = LyX::guessLyXPipeLocation();
0065 #endif // QT_LSTAT
0066 
0067         /// Finally, even if automatic detection was preferred by the user,
0068         /// still check configuration for a path if automatic detection failed
0069         if (result.isEmpty() && Preferences::instance().lyXUseAutomaticPipeDetection())
0070             result = Preferences::instance().lyXPipePath();
0071 
0072         /// Return the best found LyX pipe path
0073         return result;
0074     }
0075 };
0076 
0077 
0078 LyX::LyX(KParts::ReadOnlyPart *part, QWidget *widget)
0079         : QObject(part), d(new LyX::LyXPrivate(this, widget))
0080 {
0081     d->action = new QAction(QIcon::fromTheme(QStringLiteral("application-x-lyx")), i18n("Send to LyX/Kile"), this);
0082     part->actionCollection()->addAction(QStringLiteral("sendtolyx"), d->action);
0083     d->action->setEnabled(false);
0084     connect(d->action, &QAction::triggered, this, &LyX::sendReferenceToLyX);
0085     widget->addAction(d->action);
0086 }
0087 
0088 LyX::~LyX()
0089 {
0090     delete d;
0091 }
0092 
0093 void LyX::setReferences(const QStringList &references)
0094 {
0095     d->references = references;
0096     d->action->setEnabled(d->widget != nullptr && !d->references.isEmpty());
0097 }
0098 
0099 void LyX::sendReferenceToLyX()
0100 {
0101     const QString defaultHintOnLyXProblems = i18n("\n\nCheck that LyX or Kile are running and configured to receive references.");
0102     const QString msgBoxTitle = i18n("Send Reference to LyX");
0103     /// LyX pipe name has to determined always fresh in case LyX or Kile exited
0104     const QString pipeName = d->locateConfiguredLyXPipe();
0105 
0106     if (pipeName.isEmpty()) {
0107         KMessageBox::error(d->widget, i18n("No 'LyX server pipe' was detected.") + defaultHintOnLyXProblems, msgBoxTitle);
0108         return;
0109     }
0110 
0111     if (d->references.isEmpty()) {
0112         KMessageBox::error(d->widget, i18n("No references to send to LyX/Kile."), msgBoxTitle);
0113         return;
0114     }
0115 
0116     QFile pipe(pipeName);
0117     if (!QFileInfo::exists(pipeName) || !pipe.open(QFile::WriteOnly)) {
0118         KMessageBox::error(d->widget, i18n("Could not open LyX server pipe '%1'.", pipeName) + defaultHintOnLyXProblems, msgBoxTitle);
0119         return;
0120     }
0121 
0122     QTextStream ts(&pipe);
0123     QString msg = QString(QStringLiteral("LYXCMD:kbibtex:citation-insert:%1")).arg(d->references.join(QStringLiteral(",")));
0124 
0125 #if QT_VERSION >= 0x050e00
0126     ts << msg << Qt::endl;
0127 #else // QT_VERSION < 0x050e00
0128     ts << msg << endl;
0129 #endif // QT_VERSION >= 0x050e00
0130     ts.flush();
0131 
0132     pipe.close();
0133 }
0134 
0135 #ifdef QT_LSTAT
0136 QString LyX::guessLyXPipeLocation()
0137 {
0138     QT_STATBUF statBuffer;
0139     const QStringList nameFilter {QStringLiteral("*lyxpipe*in*")};
0140     const QVector<QDir> directoriesToScan {QDir::home(), QDir(QDir::homePath() + QStringLiteral("/.lyx")), QDir::temp()};
0141     for (const QDir &directory : directoriesToScan) {
0142         const QStringList files = directory.entryList(nameFilter, QDir::Hidden | QDir::System | QDir::Writable, QDir::Unsorted);
0143         for (const QString &filename : files) {
0144             const QString canonicalFilename = QFileInfo(directory.absolutePath() + QDir::separator() + filename).canonicalFilePath();
0145             if (QT_LSTAT(canonicalFilename.toLatin1().constData(), &statBuffer) == 0 && S_ISFIFO(statBuffer.st_mode))
0146                 return canonicalFilename;
0147         }
0148     }
0149 
0150     return QString();
0151 }
0152 #endif // QT_LSTAT