"Fossies" - the Fresh Open Source Software Archive

Member "cb2bib-2.0.1/src/c2bEditor.cpp" (12 Feb 2021, 32063 Bytes) of package /linux/privat/cb2bib-2.0.1.tar.gz:


As a special service "Fossies" has tried to format the requested source page into HTML format using (guessed) C and C++ source code syntax highlighting (style: standard) with prefixed line numbers and code folding option. Alternatively you can here view or download the uninterpreted source code file. For more information about "c2bEditor.cpp" see the Fossies "Dox" file reference documentation and the latest Fossies "Diffs" side-by-side code changes report: 2.0.0_vs_2.0.1.

    1 /***************************************************************************
    2  *   Copyright (C) 2004-2021 by Pere Constans
    3  *   constans@molspaces.com
    4  *   cb2Bib version 2.0.1. Licensed under the GNU GPL version 3.
    5  *   See the LICENSE file that comes with this distribution.
    6  ***************************************************************************/
    7 #include "c2bEditor.h"
    8 
    9 #include "bookmarkPlugin.h"
   10 #include "c2b.h"
   11 #include "c2bBibHighlighter.h"
   12 #include "c2bBibParser.h"
   13 #include "c2bExportDialog.h"
   14 #include "c2bFileDialog.h"
   15 #include "c2bPostprocess.h"
   16 #include "c2bREHighlighter.h"
   17 #include "c2bReferenceList.h"
   18 #include "c2bSettings.h"
   19 #include "c2bTextBrowser.h"
   20 #include "c2bTextEdit.h"
   21 #include "c2bUpdateMetadata.h"
   22 #include "c2bUtils.h"
   23 #include "findDialog.h"
   24 
   25 #include <bibSearcher.h>
   26 #include <texToHtml.h>
   27 
   28 #include <QCloseEvent>
   29 #include <QDir>
   30 #include <QDockWidget>
   31 #include <QLabel>
   32 #include <QMessageBox>
   33 #include <QStackedWidget>
   34 #include <QTextCursor>
   35 #include <QTextStream>
   36 
   37 
   38 /** \page bibeditor Embedded File Editor
   39 
   40 <p>GET_TABLE_OF_CONTENTS</p>
   41 
   42 
   43   cb2Bib contains a practical editor suitable to manipulate the files
   44   related to a cb2Bib session. Abbreviations, bookmarks, regular expressions,
   45   and BibTeX are readily available. On BibTeX mode, the editor contains a
   46   Reference List to ease file navigation, and to extend the editor
   47   functionality. The BibTeX editor can optionally be turned to a reference
   48   browser.
   49 
   50 
   51   \section bookmarks Bookmarks
   52 
   53   Bookmarks pointing to local or network files are available at the editor menu
   54   bar. They provide a fast access to external resources. Concretely, they are
   55   suitable for retrieving working documents, writing notes, or for accessing
   56   internet databases.
   57 
   58   The editor bookmark functionality had been introduced in the cb2Bib version
   59   0.9.3. Currently, bookmarks are set manually in the <tt>netqinf.txt</tt>
   60   file, see \ref c2bconf_files. Each bookmark is an entry line with the form
   61 \verbatim
   62 editorbookmark=Description|Target file name|Shortcut|Icon file name
   63 \endverbatim
   64     having four fields, description, target file name, shortcut, and icon
   65     file name, separated with three (required) vertical bars |.
   66 \verbatim
   67 # Bookmark Examples:
   68 # - A URL:
   69 editorbookmark=URL Description|https://www.molspaces.com/cb2bib/doc/bibeditor/||
   70 # - A separator, which is a blank line:
   71 editorbookmark=
   72 # - A TeX document, which will be opened with its default application:
   73 editorbookmark=Document Description|/home/doc/chapter1.tex||
   74 \endverbatim
   75 
   76 
   77   \section update_metadata Update Documents Metadata
   78 
   79   The Update Documents Metadata functionality is available at the Edit and
   80   context menus on the BibTeX editor mode. Documents referred in the BibTeX
   81   file tags are scanned for metadata. If the BibTeX reference does not coincide
   82   with the bibliographic metadata, the document metadata is updated. In this
   83   way, metadata is synchronized with the BibTeX file contents. A log window
   84   appears, and possible errors are reported. Reported errors are, non-existence
   85   of a document file, read-only files, mismatches between BibTeX references and
   86   the actual metadata (often due to HTML tags or other illegal characters in
   87   BibTeX), or that the writing to the document format is not implemented. Note
   88   that this process will update all documents referenced in the BibTeX file.
   89   <b>While this process is safe, it implies writing into the documents.</b>
   90   Therefore take the usual measures and backup your data. See also \ref
   91   metadata_write.
   92 
   93 
   94   \section export_entries Export Selected Entries
   95 
   96   Selected entries can be exported to a separate BibTeX document. Click on
   97   <tt>File->Export Entries</tt> menu option, and provide an export filename at
   98   the Export Dialog. Optionally, export will copy the document files attached
   99   to the citation. The copy of documents is similar to the cb2Bib
  100   'rename/copy/move' general procedure. See \ref c2bconf_documents, on <b>Set
  101   directory relative to the BibTeX File Directory</b>, for copying options.
  102   Documents will not be overwritten: copying of existing documents is skipped.
  103   Possible issues are reported in the new document, as LaTeX comments.
  104 
  105 
  106   \section c2beditor_menu Right-Click Menu Functionality
  107 
  108 \htmlonly
  109 <center><table cellpadding="4" cellspacing="2" border="1"
  110 summary="Summary table of Right-Click Menu Functionality">
  111 <tr> <th valign="top">Default Key</th> <th valign="top">Action</th></tr>
  112 <tr> <td valign="top">Ctrl+F</td> <td valign="top">Find in text</td></tr>
  113 <tr> <td valign="top"></td> <td valign="top">Toggle word wrapping</td></tr>
  114 <tr> <td valign="top"></td> <td valign="top">Selection to LaTeX</td></tr>
  115 <tr> <td valign="top"></td> <td valign="top">Selection to Unicode</td></tr>
  116 <tr> <td valign="top"></td> <td valign="top">Journals to full name</td></tr>
  117 <tr> <td valign="top"></td> <td valign="top">Journals to alternate full name</td></tr>
  118 <tr> <td valign="top"></td> <td valign="top">Journals to abbreviated name</td></tr>
  119 <tr> <td valign="top"></td> <td valign="top">Journals to alternate abbreviated name</td></tr>
  120 <tr> <td valign="top"></td> <td valign="top">Update documents metadata</td></tr>
  121 <tr> <td valign="top">Shift+Ins</td> <td valign="top">Paste current BibTeX</td></tr>
  122 <tr> <td valign="top">Alt+P</td> <td valign="top">Save and postprocess BibTeX file</td></tr>
  123 </table></center>
  124 \endhtmlonly
  125 
  126   \section references_menu Reference List Right-Click Menu Functionality
  127 
  128 \htmlonly
  129 <center><table cellpadding="4" cellspacing="2" border="1"
  130 summary="Summary table of References Right-Click Menu Functionality">
  131 <tr> <th valign="top">Default Key</th> <th valign="top">Action</th></tr>
  132 <tr> <td valign="top">Alt+C</td> <td valign="top">Cite selected entries</td></tr>
  133 <tr> <td valign="top"></td> <td valign="top">Open document file</td></tr>
  134 <tr> <td valign="top"></td> <td valign="top">Browse by DOI</td></tr>
  135 <tr> <td valign="top"></td> <td valign="top">Web search by Author</td></tr>
  136 <tr> <td valign="top"></td> <td valign="top">Web search by Title</td></tr>
  137 <tr> <td valign="top"></td> <td valign="top">Web search settings</td></tr>
  138 <tr> <td valign="top"></td> <td valign="top">Clear entry selection</td></tr>
  139 <tr> <td valign="top"></td> <td valign="top">Refresh list and browser</td></tr>
  140 </table></center>
  141 \endhtmlonly
  142 
  143   \section browser_menu BibTeX Browser Right-Click Menu Functionality
  144 
  145 \htmlonly
  146 <center><table cellpadding="4" cellspacing="2" border="1"
  147 summary="Summary table of Browser Right-Click Menu Functionality">
  148 <tr> <th valign="top">Default Key</th> <th valign="top">Action</th></tr>
  149 <tr> <td valign="top">Alt+C</td> <td valign="top">Cite selected entries</td></tr>
  150 <tr> <td valign="top"></td> <td valign="top">Local search for selected text</td></tr>
  151 <tr> <td valign="top"></td> <td valign="top">Web search for selected text</td></tr>
  152 <tr> <td valign="top"></td> <td valign="top">Web search settings</td></tr>
  153 <tr> <td valign="top"></td> <td valign="top">Clear entry selection</td></tr>
  154 <tr> <td valign="top"></td> <td valign="top">Refresh list and browser</td></tr>
  155 </table></center>
  156 \endhtmlonly
  157 
  158   \section c2beditor_qt Additional Functionality
  159 
  160 \htmlonly
  161 <center><table cellpadding="4" cellspacing="2" border="1"
  162 summary="Summary table of Additional Functionality">
  163 <tr> <td valign="top">Backspace</td> <td valign="top">Deletes the character to the left of the cursor</td></tr>
  164 <tr> <td valign="top">Delete</td> <td valign="top">Deletes the character to the right of the cursor</td></tr>
  165 <tr> <td valign="top">Ctrl+A</td> <td valign="top">Selects all text</td></tr>
  166 <tr> <td valign="top">Ctrl+C</td> <td valign="top">Copy the selected text to the clipboard</td></tr>
  167 <tr> <td valign="top">Ctrl+Insert</td> <td valign="top">Copy the selected text to the clipboard</td></tr>
  168 <tr> <td valign="top">Ctrl+K</td> <td valign="top">Deletes to the end of the line</td></tr>
  169 <tr> <td valign="top">Ctrl+V</td> <td valign="top">Pastes the clipboard text into text edit</td></tr>
  170 <tr> <td valign="top">Shift+Insert</td> <td valign="top">Pastes the clipboard text into text edit</td></tr>
  171 <tr> <td valign="top">Ctrl+X</td> <td valign="top">Deletes the selected text and copies it to the clipboard</td></tr>
  172 <tr> <td valign="top">Shift+Delete</td> <td valign="top">Deletes the selected text and copies it to the
  173 clipboard</td></tr>
  174 <tr> <td valign="top">Ctrl+Z</td> <td valign="top">Undoes the last operation</td></tr>
  175 <tr> <td valign="top">Ctrl+Y</td> <td valign="top">Redoes the last operation</td></tr>
  176 <tr> <td valign="top">LeftArrow</td> <td valign="top">Moves the cursor one character to the left</td></tr>
  177 <tr> <td valign="top">Ctrl+LeftArrow</td> <td valign="top">Moves the cursor one word to the left</td></tr>
  178 <tr> <td valign="top">RightArrow</td> <td valign="top">Moves the cursor one character to the right</td></tr>
  179 <tr> <td valign="top">Ctrl+RightArrow</td> <td valign="top">Moves the cursor one word to the right</td></tr>
  180 <tr> <td valign="top">UpArrow</td> <td valign="top">Moves the cursor one line up</td></tr>
  181 <tr> <td valign="top">Ctrl+UpArrow</td> <td valign="top">Moves the cursor one word up</td></tr>
  182 <tr> <td valign="top">DownArrow</td> <td valign="top">Moves the cursor one line down</td></tr>
  183 <tr> <td valign="top">Ctrl+Down Arrow</td> <td valign="top">Moves the cursor one word down</td></tr>
  184 <tr> <td valign="top">PageUp</td> <td valign="top">Moves the cursor one page up</td></tr>
  185 <tr> <td valign="top">PageDown</td> <td valign="top">Moves the cursor one page down</td></tr>
  186 <tr> <td valign="top">Home</td> <td valign="top">Moves the cursor to the beginning of the line</td></tr>
  187 <tr> <td valign="top">Ctrl+Home</td> <td valign="top">Moves the cursor to the beginning of the text</td></tr>
  188 <tr> <td valign="top">End</td> <td valign="top">Moves the cursor to the end of the line</td></tr>
  189 <tr> <td valign="top">Ctrl+End</td> <td valign="top">Moves the cursor to the end of the text</td></tr>
  190 <tr> <td valign="top">Alt+Wheel</td> <td valign="top">Scrolls the page horizontally</td></tr>
  191 <tr> <td valign="top">Ctrl+Wheel</td> <td valign="top">Zooms the text</td></tr>
  192 </table></center>
  193 \endhtmlonly
  194 
  195 */
  196 
  197 
  198 c2bEditor::c2bEditor(const QString& file, const Mode mode, QWidget* main, QWidget* parentw) : QMainWindow(parentw)
  199 {
  200     _editor_fn = QDir::toNativeSeparators(file);
  201     _editor_mode = mode;
  202     _c2b_mainP = main;
  203     _searcherP = 0;
  204     initEditor();
  205 }
  206 
  207 c2bEditor::c2bEditor(const QString& file, bibSearcher* searcher, QWidget* main, QWidget* parentw) : QMainWindow(parentw)
  208 {
  209     _editor_fn = QDir::toNativeSeparators(file);
  210     _editor_mode = BibTeX;
  211     _c2b_mainP = main;
  212     _searcherP = searcher;
  213     initEditor();
  214 }
  215 
  216 c2bEditor::~c2bEditor()
  217 {
  218     if (_browserP)
  219         _settingsP->setValue("c2bEditor/BrowserFontPointSize", _browserP->font().pointSize());
  220 }
  221 
  222 
  223 void c2bEditor::initEditor()
  224 {
  225     ui.setupUi(this);
  226     setAttribute(Qt::WA_DeleteOnClose);
  227 
  228     _settingsP = c2bSettingsP;
  229     if (_editor_mode == BibTeX)
  230         _bpP = c2b::bibParser();
  231     else
  232         _bpP = 0;
  233     _browserP = 0;
  234     _editorP = new c2bTextEdit(this);
  235     _referencesP = 0;
  236     _stackedWidgetP = new QStackedWidget(this);
  237     setCentralWidget(_stackedWidgetP);
  238     _stackedWidgetP->addWidget(_editorP);
  239     _textFinderP = new findDialog(this);
  240     _lineLabelP = new QLabel();
  241     _lineLabelP->setText(tr(" Line: 1  Col: 1 "));
  242     _lineLabelP->setAlignment(Qt::AlignVCenter | Qt::AlignRight);
  243     _lineLabelP->setFrameStyle(QFrame::NoFrame);
  244     _lineLabelP->setLineWidth(1);
  245     _lineLabelP->setFixedHeight(_lineLabelP->fontMetrics().height());
  246     statusBar()->addWidget(_lineLabelP, 1);
  247     connect(_editorP, SIGNAL(cursorPositionChanged()), this, SLOT(cursorPositionChanged()));
  248     _overwriteLabelP = new QLabel();
  249     _overwriteLabelP->setText(tr(" INS "));
  250     _overwriteLabelP->setAlignment(Qt::AlignVCenter | Qt::AlignRight);
  251     _overwriteLabelP->setFrameStyle(QFrame::NoFrame);
  252     _overwriteLabelP->setLineWidth(1);
  253     _overwriteLabelP->setFixedHeight(_overwriteLabelP->fontMetrics().height());
  254     statusBar()->addWidget(_overwriteLabelP);
  255     _editorP->setOverwriteMode(false);
  256     connect(_editorP, SIGNAL(overwriteModeChanged()), this, SLOT(overwriteModeChanged()));
  257     connect(ui.fileCloseAction, SIGNAL(triggered()), this, SLOT(close()));
  258     connect(ui.fileExecAction, SIGNAL(triggered()), this, SLOT(saveAndExecute()));
  259     connect(ui.fileExitAction, SIGNAL(triggered()), c2b::instance(), SLOT(exitRequested()));
  260     connect(ui.fileSaveAction, SIGNAL(triggered()), this, SLOT(fileSave()));
  261     connect(ui.fileSaveAsAction, SIGNAL(triggered()), this, SLOT(fileSaveAs()));
  262     connect(ui.helpEditorAction, SIGNAL(triggered()), this, SLOT(helpEditor()));
  263     connect(ui.helpCb2BibAction, SIGNAL(triggered()), this, SLOT(helpCb2Bib()));
  264     connect(ui.viewCb2BibAction, SIGNAL(triggered()), this, SLOT(viewCb2Bib()));
  265 
  266     // Standard shortcuts
  267     ui.fileCloseAction->setShortcut(QKeySequence(QKeySequence::Close));
  268     ui.fileOpenAction->setShortcut(QKeySequence(QKeySequence::Open));
  269     ui.fileSaveAction->setShortcut(QKeySequence(QKeySequence::Save));
  270     ui.helpEditorAction->setShortcut(QKeySequence(QKeySequence::HelpContents));
  271     ui.viewZoomInAction->setShortcut(QKeySequence(QKeySequence::ZoomIn));
  272     ui.viewZoomOutAction->setShortcut(QKeySequence(QKeySequence::ZoomOut));
  273     ui.fileExitAction->setShortcut(QKeySequence(QKeySequence::Quit));
  274     ui.fileSaveAsAction->setShortcut(QKeySequence(QKeySequence::SaveAs));
  275 
  276     // Editor Settings
  277     resize(_settingsP->value("c2bEditor/size", size()).toSize());
  278     ui.menuView->addAction(ui.toolBar->toggleViewAction());
  279     ui.setLyXPipeAction->setVisible(false);
  280     _editorP->setFont(_settingsP->c2bMonoFont);
  281     connect(ui.settingsCb2BibAction, SIGNAL(triggered()), c2b::instance(), SLOT(configure()));
  282 
  283     // Bookmarks
  284     bookmarkPlugin* bookmarks = new bookmarkPlugin(this);
  285     menuBar()->insertMenu(ui.menuSettings->menuAction(), bookmarks);
  286     connect(bookmarks, SIGNAL(openFile(QString)), this, SIGNAL(openFile(QString)));
  287     connect(bookmarks, SIGNAL(editBookmarks()), this, SIGNAL(openBookmarks()));
  288 
  289     load();
  290     setEditorMode();
  291     importActions();
  292     QApplication::processEvents(); // Qt 4.7.0 emits contentsChange with position inconsistently defined, make sure it
  293     // is not captured
  294     connect(_editorP->document(), SIGNAL(contentsChange(int,int,int)), this, SLOT(isModified(int,int,int)));
  295     connect(c2b::instance(), SIGNAL(statusMessage(QString)), this, SLOT(showMessage(QString)));
  296 }
  297 
  298 void c2bEditor::setEditorMode()
  299 {
  300     if (_editor_mode == RegExp)
  301     {
  302         _shP = new c2bREHighlighter(_editorP->document());
  303         ui.fileExecAction->setText(tr("Restart Recognition"));
  304         ui.fileExecAction->setStatusTip(tr("Restart recognition"));
  305         _settingsP->setKeysequence("Shortcuts/Editor/", ui.fileExecAction);
  306         connect(this, SIGNAL(execute()), this, SIGNAL(restartEngine()));
  307         ui.toolBar->setVisible(_settingsP->value("c2bEditor/ToolBar", true).toBool());
  308         setViewMode(true);
  309     }
  310     else if (_editor_mode == NetQInfo)
  311     {
  312         _shP = new c2bREHighlighter(_editorP->document());
  313         ui.fileExecAction->setText(tr("Restart Network Query"));
  314         ui.fileExecAction->setStatusTip(tr("Restart network query"));
  315         _settingsP->setKeysequence("Shortcuts/Editor/", ui.fileExecAction);
  316         connect(this, SIGNAL(execute()), this, SIGNAL(restartQuery()));
  317         ui.toolBar->setVisible(_settingsP->value("c2bEditor/ToolBar", true).toBool());
  318         setViewMode(true);
  319     }
  320     else if (_editor_mode == JAbbrev)
  321     {
  322         ui.fileExecAction->setVisible(false);
  323         ui.toolBar->setVisible(_settingsP->value("c2bEditor/ToolBar", true).toBool());
  324         setViewMode(true);
  325     }
  326     else if (_editor_mode == Annote)
  327     {
  328         _shP = new c2bBibHighlighter(_editorP->document());
  329         ui.fileExecAction->setText(tr("View Note in External Browser"));
  330         ui.fileExecAction->setStatusTip(tr("View Note in External Browser"));
  331         _settingsP->setKeysequence("Shortcuts/Editor/", ui.fileExecAction);
  332         _editorP->setLaTeXActions();
  333         connect(this, SIGNAL(execute()), this, SLOT(htmlView()));
  334         ui.toolBar->setVisible(_settingsP->value("c2bEditor/ToolBar", true).toBool());
  335         setViewMode(true);
  336     }
  337     else if (_editor_mode == BibTeX)
  338     {
  339         // Editor
  340         _shP = new c2bBibHighlighter(_editorP->document());
  341         ui.fileOpenAction->setVisible(true);
  342         connect(ui.fileOpenAction, SIGNAL(triggered()), this, SLOT(fileOpen()));
  343         _editorP->setBibTeXActions();
  344         connect(_editorP->pasteCurrentBibTeXAction, SIGNAL(triggered()), this, SLOT(pasteCurrentBibTeX()));
  345         connect(_editorP->journalsToAbbreviatedAction, SIGNAL(triggered()), this, SLOT(journalsToAbbreviated()));
  346         connect(_editorP->journalsToAlternateAbbreviatedAction, SIGNAL(triggered()), this,
  347                 SLOT(journalsToAlternateAbbreviated()));
  348         connect(_editorP->journalsToFullAction, SIGNAL(triggered()), this, SLOT(journalsToFull()));
  349         connect(_editorP->journalsToAlternateFullAction, SIGNAL(triggered()), this, SLOT(journalsToAlternateFull()));
  350         connect(_editorP->updateMetadataAction, SIGNAL(triggered()), this, SLOT(updateMetadata()));
  351         connect(_c2b_mainP, SIGNAL(addedBibToFile(QString)), this, SLOT(reload(QString)));
  352         ui.fileExecAction->setText(tr("Save and Postprocess"));
  353         ui.fileExecAction->setStatusTip(tr("Save and postprocess"));
  354         _settingsP->setKeysequence("Shortcuts/Editor/", ui.fileExecAction);
  355         connect(this, SIGNAL(execute()), this, SLOT(postProcess()));
  356 
  357         // Browser
  358         _browserP = new c2bTextBrowser(this);
  359         _browserP->setFont(
  360             QFont(QFont().family(), _settingsP->value("c2bEditor/BrowserFontPointSize", QFont().pointSize()).toInt()));
  361         _stackedWidgetP->addWidget(_browserP);
  362         ui.viewEditorModeAction->setVisible(true);
  363         _settingsP->setKeysequence("Shortcuts/Editor/", ui.viewEditorModeAction);
  364         connect(ui.viewEditorModeAction, SIGNAL(triggered(bool)), this, SLOT(setViewMode(bool)));
  365         connect(ui.viewZoomInAction, SIGNAL(triggered()), _browserP, SLOT(zoomIn()));
  366         connect(ui.viewZoomOutAction, SIGNAL(triggered()), _browserP, SLOT(zoomOut()));
  367 
  368         // Reference List
  369         createReferenceList();
  370         _referencesP->loadList(_editorP->toPlainText(), _searcherP);
  371         bool edit_mode(false);
  372         if (_searcherP)
  373         {
  374             edit_mode = (_searcherP->hitsCount() == 0 && _searcherP->errorsCount() > 0);
  375             connect(_referencesP, SIGNAL(openFile(QString)), this, SIGNAL(openFile(QString)));
  376         }
  377         if (!_edit_reference_at_position.isEmpty())
  378         {
  379             edit_mode = true;
  380             _referencesP->goToReference(_edit_reference_at_position.toInt());
  381         }
  382         ui.viewEditorModeAction->setChecked(edit_mode);
  383         setViewMode(edit_mode);
  384         ui.setLyXPipeAction->setVisible(true);
  385         _settingsP->setKeysequence("Shortcuts/Editor/", ui.setLyXPipeAction);
  386 
  387         // Export entries
  388         ui.fileExportEntriesAction->setVisible(true);
  389         _settingsP->setKeysequence("Shortcuts/Editor/", ui.fileExportEntriesAction);
  390         connect(ui.fileExportEntriesAction, SIGNAL(triggered()), this, SLOT(exportEntries()));
  391         connect(_referencesP, SIGNAL(hasSelectedItems(bool)), ui.fileExportEntriesAction, SLOT(setEnabled(bool)));
  392     }
  393     else
  394         c2bUtils::debug(tr("c2bEditor::setEditorMode: '%1' invalid Editor Mode.").arg(_editor_mode));
  395 }
  396 
  397 void c2bEditor::importActions()
  398 {
  399     QList<QAction*> acts = _textFinderP->actions();
  400     for (int i = 0; i < acts.count(); ++i)
  401         ui.menuEdit->addAction(acts.at(i));
  402     acts = _editorP->actions();
  403     for (int i = 0; i < acts.count(); ++i)
  404         ui.menuEdit->addAction(acts.at(i));
  405     if (_browserP)
  406     {
  407         ui.menuEdit->addSeparator();
  408         acts = _browserP->actions();
  409         for (int i = 0; i < acts.count(); ++i)
  410             ui.menuEdit->addAction(acts.at(i));
  411     }
  412 }
  413 
  414 void c2bEditor::createReferenceList()
  415 {
  416     _dockWidgetP = new QDockWidget(this);
  417     _dockWidgetP->setObjectName("dwRList");
  418     _referencesP = new c2bReferenceList(_editorP, _browserP, _dockWidgetP);
  419     addDockWidget(Qt::BottomDockWidgetArea, _dockWidgetP);
  420     _dockWidgetP->setWidget(_referencesP);
  421     _dockWidgetP->setWindowTitle("Reference List");
  422     QByteArray state = _settingsP->value("c2bEditor/state").toByteArray();
  423     restoreState(state);
  424     ui.menuView->addAction(_dockWidgetP->toggleViewAction());
  425     // State contains toolBar info, too, but it can be changed from non BibTeX editors
  426     // State can not be used for non BibTeX editors. They don't have referenceList.
  427     ui.toolBar->setVisible(_settingsP->value("c2bEditor/ToolBar", true).toBool());
  428     connect(ui.setLyXPipeAction, SIGNAL(triggered()), _referencesP, SLOT(setLyXPipe()));
  429 }
  430 
  431 void c2bEditor::closeEvent(QCloseEvent* qevent)
  432 {
  433     if (closeEditor())
  434         qevent->accept();
  435     else
  436         qevent->ignore();
  437 }
  438 
  439 bool c2bEditor::closeEditor()
  440 {
  441     // Use _is_modified_by_user to check if closing is possible. This way,
  442     // no question is asked to exit browsing of search results. Do not use
  443     // here ui.fileSaveAction->isEnabled().
  444     if (_is_modified_by_user)
  445     {
  446         const int button(QMessageBox::information(
  447                              this, tr("Information - cb2Bib"), tr("The document has been modified.\nDo you want to save the changes?"),
  448                              QMessageBox::Save | QMessageBox::Discard | QMessageBox::Cancel, QMessageBox::Save));
  449         if (button == QMessageBox::Save)
  450         {
  451             if (!fileSave())
  452                 return false;
  453         }
  454         else if (button == QMessageBox::Cancel)
  455             return false;
  456     }
  457     _settingsP->setValue("c2bEditor/size", size());
  458     if (_editor_mode == BibTeX)
  459         _settingsP->setValue("c2bEditor/state", saveState());
  460     _settingsP->setValue("c2bEditor/ToolBar", !ui.toolBar->isHidden());
  461     return true;
  462 }
  463 
  464 void c2bEditor::isModified(int position, int charsRemoved, int charsAdded)
  465 {
  466     if (position == 0 && charsAdded == charsRemoved)
  467         return;
  468     ui.fileSaveAction->setEnabled(true);
  469     setWindowModified(true);
  470     _is_modified_by_user = true;
  471 }
  472 
  473 void c2bEditor::fileOpen()
  474 {
  475     if (_editor_mode == BibTeX)
  476     {
  477         const QString filename(
  478             c2bFileDialog::getOpenFilename(this, "Select a BibTeX filename", _editor_fn, "BibTeX (*.bib)"));
  479         if (!filename.isEmpty())
  480             emit openFile(filename);
  481     }
  482 }
  483 
  484 bool c2bEditor::fileSave()
  485 {
  486     if (_editor_fn.contains("unnamed_"))
  487         return fileSaveAs();
  488     QFile file(_editor_fn);
  489     if (!file.open(QIODevice::WriteOnly | QIODevice::Text))
  490     {
  491         QMessageBox::warning(
  492             this, tr("Warning - cb2Bib"),
  493             tr("Unable to open the file %1 for writing.\nError: '%2'.").arg(_editor_fn, file.errorString()),
  494             QMessageBox::Ok);
  495         return false;
  496     }
  497     QTextStream stream(&file);
  498     stream.setCodec("UTF-8");
  499     stream.setAutoDetectUnicode(true);
  500     stream << _editorP->toPlainText();
  501     ui.fileSaveAction->setEnabled(false);
  502     _editorP->document()->setModified(false);
  503     setWindowModified(false);
  504     _is_modified_by_user = false;
  505     return true;
  506 }
  507 
  508 bool c2bEditor::fileSaveAs()
  509 {
  510     QString filename;
  511     if (_editor_mode == BibTeX)
  512         filename = c2bFileDialog::getSaveFilename(this, QString(), _editor_fn, "BibTeX (*.bib);;All (*)");
  513     else if (_editor_mode == Annote)
  514         filename = c2bFileDialog::getSaveFilename(this, QString(), _editor_fn, "LaTeX (*.tex);;All (*)");
  515     else
  516         filename = c2bFileDialog::getSaveFilename(this, QString(), _editor_fn, "Text (*.txt);;All (*)");
  517     if (filename.isEmpty() || filename.contains("unnamed_"))
  518         return false;
  519     const QString old_name(_editor_fn);
  520     _editor_fn = filename;
  521     setWindowTitle(tr("%1[*] - cb2Bib").arg(_editor_fn));
  522     _editorP->setEditorFilename(_editor_fn);
  523     emit editFileRenamed(old_name, _editor_fn);
  524     return fileSave();
  525 }
  526 
  527 void c2bEditor::saveAndExecute()
  528 {
  529     // Use ui.fileSaveAction->isEnabled() instead of _is_modified_by_user.
  530     // If browsing search results there is no file on disk.
  531     if (ui.fileSaveAction->isEnabled())
  532     {
  533         if (fileSave())
  534             emit execute();
  535     }
  536     else
  537         emit execute();
  538 }
  539 
  540 void c2bEditor::load()
  541 {
  542     bool modified_flag(false);
  543     QFileInfo fi(_editor_fn);
  544     if (_editor_fn.isEmpty() || fi.isDir()) // Set an appropriate working name
  545     {
  546         QStringList unamedList;
  547         foreach (QWidget* widget, QApplication::topLevelWidgets())
  548         {
  549             if (widget->inherits("c2bEditor"))
  550                 unamedList.append(widget->objectName());
  551         }
  552         int i(1);
  553         while (unamedList.indexOf(QRegExp(QString(".*unnamed_%1.bib").arg(i))) > -1)
  554             ++i;
  555         _editor_fn =
  556             QDir::toNativeSeparators(QDir::cleanPath(_editor_fn + QDir::separator() + QString("unnamed_%1.bib").arg(i)));
  557         if (_searcherP)
  558         {
  559             _editorP->setPlainText(_searcherP->logString() + _searcherP->hitsString());
  560             modified_flag = true;
  561         }
  562     }
  563     else
  564     {
  565         QRegExp edit_ref_id(":(\\d+)$");
  566         if (edit_ref_id.indexIn(_editor_fn) > -1)
  567         {
  568             _edit_reference_at_position = edit_ref_id.cap(1);
  569             _editor_fn.remove(edit_ref_id);
  570         }
  571         QFile file(_editor_fn);
  572         if (!file.open(QIODevice::ReadOnly | QIODevice::Text))
  573         {
  574             QMessageBox::warning(
  575                 _c2b_mainP, tr("Warning - cb2Bib"),
  576                 tr("Unable to open the file %1 for reading.\nError: '%2'.").arg(_editor_fn, file.errorString()),
  577                 QMessageBox::Ok);
  578         }
  579         else
  580         {
  581             QTextStream stream(&file);
  582             stream.setCodec("UTF-8");
  583             stream.setAutoDetectUnicode(true);
  584             _editorP->setPlainText(stream.readAll());
  585         }
  586     }
  587     setWindowTitle(tr("%1[*] - cb2Bib").arg(_editor_fn));
  588     _editorP->setEditorFilename(_editor_fn);
  589     ui.fileSaveAction->setEnabled(modified_flag);
  590     _editorP->document()->setModified(modified_flag);
  591     setWindowModified(modified_flag);
  592     _is_modified_by_user = false;
  593 }
  594 
  595 void c2bEditor::reload(const QString& fn)
  596 {
  597     // This function must be called ONLY in BibTeX mode
  598     // Pointers are undefined otherwise
  599     if (_editor_mode != BibTeX || _editor_fn != fn)
  600         return;
  601 
  602     if (ui.fileSaveAction->isEnabled())
  603     {
  604         QMessageBox msgBox(this);
  605         msgBox.addButton(tr("Discard and Reload"), QMessageBox::AcceptRole);
  606         msgBox.addButton(QMessageBox::Cancel);
  607         msgBox.setDefaultButton(msgBox.addButton(QMessageBox::Save));
  608         msgBox.setWindowTitle(tr("Information - cb2Bib"));
  609         msgBox.setText(tr("The document has been modified on disk when the reference was inserted. "
  610                           "No automatic reloading is done because it also has local changes. "
  611                           "To preserve local changes press Save and insert again the last reference.\n\n"
  612                           "Do you want to save the changes?"));
  613         msgBox.setIcon(QMessageBox::Information);
  614         const int button(msgBox.exec());
  615         if (button == QMessageBox::Save)
  616         {
  617             fileSave();
  618             _referencesP->refreshList();
  619             return;
  620         }
  621         else if (button == QMessageBox::Cancel)
  622             return;
  623     }
  624     load();
  625     _referencesP->refreshList();
  626     QTextCursor cur = _editorP->textCursor();
  627     cur.movePosition(QTextCursor::End, QTextCursor::MoveAnchor);
  628     _editorP->setTextCursor(cur);
  629     _editorP->ensureCursorVisible();
  630 }
  631 
  632 void c2bEditor::exportEntries()
  633 {
  634     const QStringList keys(_referencesP->selectedKeys());
  635     if (keys.count() == 0)
  636         return;
  637     c2bExportDialog ed(_editor_fn, _editorP->toPlainText(), keys, this);
  638     if (ed.exec())
  639         emit openFile(ed.exportFilename());
  640 }
  641 
  642 void c2bEditor::pasteCurrentBibTeX()
  643 {
  644     _editorP->insertPlainText(_bpP->toBibTeX(false));
  645 }
  646 
  647 void c2bEditor::journalsToFull()
  648 {
  649     QApplication::setOverrideCursor(QCursor(Qt::WaitCursor));
  650     const QString text(_bpP->setJournalsToFull(_editorP->toPlainText(), false));
  651     _editorP->updatePlainText(text);
  652     QApplication::restoreOverrideCursor();
  653 }
  654 
  655 void c2bEditor::journalsToAlternateFull()
  656 {
  657     QApplication::setOverrideCursor(QCursor(Qt::WaitCursor));
  658     const QString text(_bpP->setJournalsToFull(_editorP->toPlainText(), true));
  659     _editorP->updatePlainText(text);
  660     QApplication::restoreOverrideCursor();
  661 }
  662 
  663 void c2bEditor::journalsToAbbreviated()
  664 {
  665     QApplication::setOverrideCursor(QCursor(Qt::WaitCursor));
  666     const QString text(_bpP->setJournalsToAbbreviated(_editorP->toPlainText(), false));
  667     _editorP->updatePlainText(text);
  668     QApplication::restoreOverrideCursor();
  669 }
  670 
  671 void c2bEditor::journalsToAlternateAbbreviated()
  672 {
  673     QApplication::setOverrideCursor(QCursor(Qt::WaitCursor));
  674     const QString text(_bpP->setJournalsToAbbreviated(_editorP->toPlainText(), true));
  675     _editorP->updatePlainText(text);
  676     QApplication::restoreOverrideCursor();
  677 }
  678 
  679 void c2bEditor::updateMetadata()
  680 {
  681     c2bUpdateMetadata um(this);
  682     um.update(_editor_fn, _editorP->toPlainText());
  683 }
  684 
  685 void c2bEditor::htmlView()
  686 {
  687     QApplication::setOverrideCursor(QCursor(Qt::WaitCursor));
  688     const QString html_filename(_editor_fn + ".html");
  689     texToHtml t2h;
  690     t2h.toHtml(c2bUtils::fileToString(_editor_fn), html_filename);
  691     c2bUtils::openFile(html_filename);
  692     QApplication::restoreOverrideCursor();
  693 }
  694 
  695 void c2bEditor::postProcess()
  696 {
  697     c2bPostprocess* ppBib = new c2bPostprocess(_editor_fn, this);
  698     ppBib->show();
  699 }
  700 
  701 void c2bEditor::helpEditor()
  702 {
  703     c2bUtils::displayHelp("https://www.molspaces.com/cb2bib/doc/bibeditor/");
  704 }
  705 
  706 void c2bEditor::helpCb2Bib()
  707 {
  708     const QString umanual(QDir::cleanPath(_settingsP->applicationDataDir() + "/doc/cb2bib_user_manual.pdf"));
  709     if (QFileInfo::exists(umanual))
  710         c2bUtils::displayHelp(umanual);
  711     else
  712         c2bUtils::displayHelp("https://www.molspaces.com/cb2bib/doc/contents/");
  713 }
  714 
  715 void c2bEditor::viewCb2Bib()
  716 {
  717     c2bUtils::setWidgetOnTop(_c2b_mainP);
  718 }
  719 
  720 void c2bEditor::setViewMode(bool edit_mode)
  721 {
  722     QList<QAction*> acts;
  723     if (edit_mode)
  724     {
  725         _textFinderP->setEditor(_editorP);
  726         if (_browserP)
  727         {
  728             acts = _browserP->actions();
  729             for (int i = 0; i < acts.count(); ++i)
  730                 acts.at(i)->setVisible(false);
  731             ui.viewZoomInAction->setVisible(false);
  732             ui.viewZoomOutAction->setVisible(false);
  733         }
  734         acts = _editorP->actions();
  735         for (int i = 0; i < acts.count(); ++i)
  736             acts.at(i)->setVisible(true);
  737         _overwriteLabelP->setVisible(true);
  738         _lineLabelP->setVisible(true);
  739         _stackedWidgetP->setCurrentWidget(_editorP);
  740     }
  741     else
  742     {
  743         // Browser defined
  744         _textFinderP->setEditor(_browserP);
  745         acts = _editorP->actions();
  746         for (int i = 0; i < acts.count(); ++i)
  747             acts.at(i)->setVisible(false);
  748         acts = _browserP->actions();
  749         for (int i = 0; i < acts.count(); ++i)
  750             acts.at(i)->setVisible(true);
  751         ui.viewZoomInAction->setVisible(true);
  752         ui.viewZoomOutAction->setVisible(true);
  753         _overwriteLabelP->setVisible(false);
  754         _lineLabelP->setVisible(false);
  755         _stackedWidgetP->setCurrentWidget(_browserP);
  756     }
  757 }
  758 
  759 void c2bEditor::showMessage(const QString& ms)
  760 {
  761     statusBar()->showMessage(ms, C2B_MESSAGE_TIME);
  762 }
  763 
  764 void c2bEditor::cursorPositionChanged()
  765 {
  766     int ln, lp;
  767     _editorP->cursorPosition(&ln, &lp);
  768     _lineLabelP->setText(tr(" Line: %1  Col: %2 ").arg(ln).arg(lp));
  769 }
  770 
  771 void c2bEditor::overwriteModeChanged()
  772 {
  773     if (_editorP->overwriteMode())
  774         _overwriteLabelP->setText(tr(" OVR "));
  775     else
  776         _overwriteLabelP->setText(tr(" INS "));
  777 }