]> git.lyx.org Git - lyx.git/blobdiff - src/frontends/qt/GuiLyXFiles.cpp
Make string-widget combination more l7n friendly
[lyx.git] / src / frontends / qt / GuiLyXFiles.cpp
index 096a390d644135e7aae1ea51b611e5289f26b242..1bfbdbb5ce2b5dd620fd922db2cfa33b2e7b5fc6 100644 (file)
 #include "qt_helpers.h"
 
 #include "FileDialog.h"
-#include "Buffer.h"
-#include "BufferParams.h"
 #include "FuncRequest.h"
 #include "Language.h"
 #include "LyXRC.h"
 
 #include "support/environment.h"
-#include "support/filetools.h"
 #include "support/gettext.h"
 #include "support/lstrings.h"
 #include "support/Messages.h"
 #include "support/qstring_helpers.h"
 #include "support/Package.h"
 
+#include <QVector>
 #include <QDirIterator>
 #include <QTreeWidget>
 
@@ -40,7 +38,7 @@ namespace frontend {
 
 namespace {
 
-QString const guiString(QString in)
+QString const guiString(QString const & in)
 {
        // recode specially encoded chars in file names (URL encoding and underbar)
        return QString::fromUtf8(QByteArray::fromPercentEncoding(in.toUtf8())).replace('_', ' ');
@@ -79,7 +77,7 @@ QMap<QString, QString> GuiLyXFiles::getFiles()
                     << toqstr(system);
 
        for (int i = 0; i < dirs.size(); ++i) {
-               QString const dir = dirs.at(i);
+               QString const dir = dirs.at(i);
                QDirIterator it(dir, QDir::Files, QDirIterator::Subdirectories);
                while (it.hasNext()) {
                        QString fn(QFile(it.next()).fileName());
@@ -152,7 +150,6 @@ QMap<QString, QString> GuiLyXFiles::getFiles()
                ++i;
        }
        setLanguage();
-       languageLA->setText(qt_("Preferred &Language:"));
        return result;
 }
 
@@ -189,19 +186,11 @@ GuiLyXFiles::GuiLyXFiles(GuiView & lv)
 
        // The filter bar
        filter_ = new FancyLineEdit(this);
-       filter_->setButtonPixmap(FancyLineEdit::Right, getPixmap("images/", "editclear", "svgz,png"));
-       filter_->setButtonVisible(FancyLineEdit::Right, true);
-       filter_->setButtonToolTip(FancyLineEdit::Right, qt_("Clear text"));
-       filter_->setAutoHideButton(FancyLineEdit::Right, true);
+       filter_->setClearButton(true);
        filter_->setPlaceholderText(qt_("All available files"));
        filter_->setToolTip(qt_("Enter string to filter the list of available files"));
-#if (QT_VERSION < 0x050000)
-       connect(filter_, SIGNAL(downPressed()),
-               filesLW, SLOT(setFocus()));
-#else
        connect(filter_, &FancyLineEdit::downPressed,
-               filesLW, [=](){ focusAndHighlight(filesLW); });
-#endif
+               filesLW, [this](){ focusAndHighlight(filesLW); });
 
        filterBarL->addWidget(filter_, 0);
        findKeysLA->setBuddy(filter_);
@@ -210,9 +199,9 @@ GuiLyXFiles::GuiLyXFiles(GuiView & lv)
                this, SLOT(slotButtonBox(QAbstractButton *)));
 
        connect(filesLW, SIGNAL(itemClicked(QTreeWidgetItem *, int)),
-               this, SLOT(changed_adaptor()));
+               this, SLOT(fileSelectionChanged()));
        connect(filesLW, SIGNAL(itemSelectionChanged()),
-               this, SLOT(changed_adaptor()));
+               this, SLOT(fileSelectionChanged()));
        connect(filter_, SIGNAL(textEdited(QString)),
                this, SLOT(filterLabels()));
        connect(filter_, SIGNAL(rightButtonClicked()),
@@ -252,8 +241,14 @@ bool GuiLyXFiles::translateName() const
 }
 
 
-void GuiLyXFiles::changed_adaptor()
+void GuiLyXFiles::fileSelectionChanged()
 {
+       if (!filesLW->currentItem()
+           || !filesLW->currentItem()->data(0, Qt::UserRole).toString().endsWith(getSuffix())) {
+               // not a file (probably a header)
+               bc().setValid(false);
+               return;
+       }
        changed();
 }
 
@@ -277,9 +272,11 @@ void GuiLyXFiles::on_languageCO_activated(int i)
 
 void GuiLyXFiles::on_filesLW_itemDoubleClicked(QTreeWidgetItem * item, int)
 {
-       if (!item->data(0, Qt::UserRole).toString().endsWith(getSuffix()))
+       if (!item || !item->data(0, Qt::UserRole).toString().endsWith(getSuffix())) {
                // not a file (probably a header)
+               bc().setValid(false);
                return;
+       }
 
        applyView();
        dispatchParams();
@@ -288,10 +285,17 @@ void GuiLyXFiles::on_filesLW_itemDoubleClicked(QTreeWidgetItem * item, int)
 
 void GuiLyXFiles::on_filesLW_itemClicked(QTreeWidgetItem * item, int)
 {
+       if (!item) {
+               bc().setValid(false);
+               return;
+       }
+
        QString const data = item->data(0, Qt::UserRole).toString();
-       if (!data.endsWith(getSuffix()))
+       if (!data.endsWith(getSuffix())) {
                // not a file (probably a header)
+               bc().setValid(false);
                return;
+       }
 
        languageCO->clear();
        QMap<QString, QString>::const_iterator i =available_languages_.constBegin();
@@ -301,9 +305,6 @@ void GuiLyXFiles::on_filesLW_itemClicked(QTreeWidgetItem * item, int)
                        languageCO->addItem(i.value(), i.key());
                ++i;
        }
-       languageLA->setText(qt_("File &Language:"));
-       languageCO->setToolTip(qt_("All available languages of the selected file are displayed here.\n"
-                                  "The selected language version will be opened."));
        setLanguage();
        QString const realpath = getRealPath();
        filesLW->currentItem()->setData(0, Qt::ToolTipRole, realpath);
@@ -318,8 +319,18 @@ void GuiLyXFiles::on_filesLW_itemClicked(QTreeWidgetItem * item, int)
 void GuiLyXFiles::setLanguage()
 {
        // Enable language selection only if there is a selection.
-       languageCO->setEnabled(languageCO->count() > 1);
-       languageLA->setEnabled(languageCO->count() > 1);
+       bool const item_selected =  filesLW->currentItem();
+       bool const language_alternatives = languageCO->count() > 1;
+       languageCO->setEnabled(item_selected && language_alternatives);
+       languageLA->setEnabled(item_selected && language_alternatives);
+       if (item_selected && language_alternatives)
+               languageCO->setToolTip(qt_("All available languages of the selected file are displayed here.\n"
+                                          "The selected language version will be opened."));
+       else if (item_selected)
+               languageCO->setToolTip(qt_("No alternative language versions available for the selected file."));
+       else
+               languageCO->setToolTip(qt_("If alternative languages are available for a given file,\n"
+                                          "they can be chosen here if a file is selected."));
        // first try last setting
        if (!savelang_.isEmpty()) {
                int index = languageCO->findData(savelang_);
@@ -401,6 +412,8 @@ void GuiLyXFiles::updateContents()
        filesLW->clear();
        QIcon user_icon(getPixmap("images/", "lyxfiles-user", "svgz,png"));
        QIcon system_icon(getPixmap("images/", "lyxfiles-system", "svgz,png"));
+       QIcon user_folder_icon(getPixmap("images/", "lyxfiles-user-folder", "svgz,png"));
+       QIcon system_folder_icon(getPixmap("images/", "lyxfiles-system-folder", "svgz,png"));
        QStringList cats;
        QMap<QString, QString>::const_iterator it = files.constBegin();
        QFont capfont;
@@ -436,8 +449,8 @@ void GuiLyXFiles::updateContents()
                        guiname = qt_("Default Template");
                else if (translateName())
                        guiname = toqstr(translateIfPossible(qstring_to_ucs4(guiString(guiname))));
-               QIcon file_icon = (realpath.startsWith(toqstr(package().user_support().absFileName()))) ?
-                               user_icon : system_icon;
+               bool const user = realpath.startsWith(toqstr(package().user_support().absFileName()));
+               QIcon file_icon = user ? user_icon : system_icon;
                item->setIcon(0, file_icon);
                item->setData(0, Qt::UserRole, it.key());
                item->setData(0, Qt::DisplayRole, guiname);
@@ -445,19 +458,22 @@ void GuiLyXFiles::updateContents()
                if (subcat.isEmpty())
                        catItem->addChild(item);
                else {
-                       QTreeWidgetItem * subcatItem = new QTreeWidgetItem();
+                       QTreeWidgetItem * subcatItem = nullptr;
                        if (cats.contains(catsave)) {
                                QList<QTreeWidgetItem *> pcats = filesLW->findItems(cat, Qt::MatchExactly);
-                               for (int iit = 0; iit < pcats.size(); ++iit) {
-                                       for (int cit = 0; cit < pcats.at(iit)->childCount(); ++cit) {
-                                               if (pcats.at(iit)->child(cit)->text(0) == subcat) {
-                                                       subcatItem = pcats.at(iit)->child(cit);
+                               for (auto const & pcat : pcats) {
+                                       for (int cit = 0; cit < pcat->childCount(); ++cit) {
+                                               if (pcat->child(cit)->text(0) == subcat) {
+                                                       subcatItem = pcat->child(cit);
                                                        break;
                                                }
                                        }
                                }
-                       } else {
+                       }
+                       if (!subcatItem) {
+                               subcatItem = new QTreeWidgetItem();
                                subcatItem->setText(0, subcat);
+                               file_icon = user ? user_folder_icon : system_folder_icon;
                                subcatItem->setIcon(0, file_icon);
                                cats << catsave;
                        }
@@ -491,12 +507,43 @@ void GuiLyXFiles::filterLabels()
 {
        Qt::CaseSensitivity cs = csFindCB->isChecked() ?
                Qt::CaseSensitive : Qt::CaseInsensitive;
+       // Collect "active" categories (containing entries
+       // that match the filter)
+       QVector<QTreeWidgetItem*> activeCats;
        QTreeWidgetItemIterator it(filesLW);
        while (*it) {
-               (*it)->setHidden(
-                       (*it)->childCount() == 0
-                       && !(*it)->text(0).contains(filter_->text(), cs)
-               );
+               if ((*it)->childCount() > 0) {
+                       // Unhide parents (will be hidden
+                       // below if necessary)
+                       (*it)->setHidden(false);
+                       ++it;
+                       continue;
+               }
+               bool const match = (*it)->text(0).contains(filter_->text(), cs);
+               if (match) {
+                       // Register parents of matched entries
+                       // so we don't hide those later.
+                       QTreeWidgetItem * twi = *it;
+                       while (true) {
+                               if (!twi->parent())
+                                       break;
+                               activeCats << twi->parent();
+                               // ascend further up if possible
+                               twi = twi->parent();
+                       }
+               }
+               (*it)->setHidden(!match);
+               ++it;
+       }
+       // Iterate through parents once more
+       // to hide empty categories
+       it = QTreeWidgetItemIterator(filesLW);
+       while (*it) {
+               if ((*it)->childCount() == 0) {
+                       ++it;
+                       continue;
+               }
+               (*it)->setHidden(!activeCats.contains(*it));
                ++it;
        }
 }
@@ -510,7 +557,7 @@ void GuiLyXFiles::resetFilter()
 
 QString const GuiLyXFiles::getRealPath(QString relpath)
 {
-       if (relpath.isEmpty())
+       if (relpath.isEmpty() && filesLW->currentItem() != nullptr)
                relpath = filesLW->currentItem()->data(0, Qt::UserRole).toString();
        QString const language = languageCO->itemData(languageCO->currentIndex()).toString();
        if (localizations_.contains(relpath)) {
@@ -552,7 +599,7 @@ void GuiLyXFiles::passParams(string const & data)
 }
 
 
-void GuiLyXFiles::selectItem(QString const item)
+void GuiLyXFiles::selectItem(QString const item)
 {
        /* Using an intermediary variable flags is needed up to at least
         * Qt 5.5 because of a subtle namespace issue. See:
@@ -586,7 +633,7 @@ void GuiLyXFiles::dispatchParams()
        string arg;
        if (type_ == "templates")
                arg = "newfile ";
-       arg += fromqstr(file_);
+       arg += quoteName(fromqstr(file_));
        FuncCode const lfun = getLfun();
 
        if (lfun == LFUN_NOACTION)
@@ -606,8 +653,6 @@ FuncCode GuiLyXFiles::getLfun() const
        return LFUN_NOACTION;
 }
 
-Dialog * createGuiLyXFiles(GuiView & lv) { return new GuiLyXFiles(lv); }
-
 
 } // namespace frontend
 } // namespace lyx