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