Enable the user to input "file names with spaces" only if LaTeX can

handle them.


git-svn-id: svn://svn.lyx.org/lyx/lyx-devel/trunk@9946 a592a061-630c-0410-9148-cb99ea01b6c8
This commit is contained in:
Angus Leeming 2005-05-16 09:14:18 +00:00
parent 270bb796aa
commit 36c3528db8
21 changed files with 342 additions and 68 deletions

View File

@ -1,3 +1,9 @@
2005-05-13 Angus Leeming <leeming@lyx.org>
* helper_funcs.C (browseFile, browseDir): remove the loop that tested
whether the returned file name is valid in order to break out of the
loop.
2005-05-08 Angus Leeming <leeming@lyx.org>
* Kernel.h (KernelDocType): wrapper class for the Kernel::DocTypes

View File

@ -16,10 +16,10 @@
#include "gettext.h"
#include "frontends/Alert.h"
#include "frontends/FileDialog.h"
#include "support/filetools.h"
#include "support/lstrings.h"
#include "support/package.h"
using std::pair;
@ -61,27 +61,12 @@ string const browseFile(string const & filename,
FileDialog::Result result;
while (true) {
if (save)
result = fileDlg.save(lastPath, filters,
OnlyFilename(filename));
else
result = fileDlg.open(lastPath, filters,
OnlyFilename(filename));
if (result.second.empty())
return result.second;
lastPath = OnlyPath(result.second);
if (result.second.find_first_of("#~$% ") == string::npos)
break;
Alert::error(_("Invalid filename"),
_("Filename can't contain any "
"of these characters:\n"
"space, '#', '~', '$' or '%'."));
}
if (save)
result = fileDlg.save(lastPath, filters,
OnlyFilename(filename));
else
result = fileDlg.open(lastPath, filters,
OnlyFilename(filename));
return result.second;
}
@ -150,25 +135,8 @@ string const browseDir(string const & pathname,
FileDialog fileDlg(title, LFUN_SELECT_FILE_SYNC, dir1, dir2);
FileDialog::Result result;
while (true) {
result = fileDlg.opendir(lastPath,
OnlyFilename(pathname));
if (result.second.empty())
return result.second;
lastPath = OnlyPath(result.second);
if (result.second.find_first_of("#~$% ") == string::npos)
break;
Alert::error(_("Invalid filename"),
_("Filename can't contain any "
"of these characters:\n"
"space, '#', '~', '$' or '%'."));
}
FileDialog::Result const result =
fileDlg.opendir(lastPath, OnlyFilename(pathname));
return result.second;
}

View File

@ -1,3 +1,22 @@
2005-05-13 Angus Leeming <leeming@lyx.org>
* QBibtex.C (build_dialog):
* QBibtexDialog.C (c-tor, bibEDChanged, addPressed): add a
PathValidator of the add_->BibED widget and use it to control
the activation state of the "Add" button.
* QExternal.C (build_dialog, update_contents):
* QExternalDialog.C (c-tor): add a PathValidator of the fileED
widget.
* QGraphics.C (build_dialog, update_contents):
* QGraphicsDialog.C (c-tor): add a PathValidator of the filename
widget.
* QInclude.C (build_dialog, update_contents):
* QIncludeDialog.C (c-tor): add a PathValidator of the filenameED
widget.
2005-05-09 Michael Schmitt <michael.schmitt@teststep.org>
* *.C: strip "LyX: " prefix from dialog titles; harmonize

View File

@ -17,6 +17,9 @@
#include "ui/QBibtexAddDialogBase.h"
#include "Qt2BC.h"
#include "qt_helpers.h"
#include "validators.h"
#include "lyxrc.h"
#include "controllers/ControlBibtex.h"
@ -66,6 +69,11 @@ void QBibtex::build_dialog()
void QBibtex::update_contents()
{
PathValidator * path_validator =
getPathValidator(dialog_->add_->bibED);
if (path_validator)
path_validator->setChecker(kernel().docType(), lyxrc);
bool bibtopic = controller().usingBibtopic();
dialog_->databaseLB->clear();

View File

@ -13,10 +13,17 @@
#include "QBibtexDialog.h"
#include "ui/QBibtexAddDialogBase.h"
#include "QBibtex.h"
#include "checkedwidgets.h"
#include "Qt2BC.h"
#include "qt_helpers.h"
#include "validators.h"
#include "controllers/ControlBibtex.h"
#include "controllers/ButtonPolicies.h"
#include "support/filetools.h"
#include "support/lstrings.h"
#include <qpushbutton.h>
#include <qcombobox.h>
@ -24,6 +31,7 @@
#include <qlistbox.h>
using lyx::support::ChangeExtension;
using lyx::support::trim;
using std::string;
@ -40,12 +48,41 @@ QBibtexDialog::QBibtexDialog(QBibtex * form)
form, SLOT(slotClose()));
add_ = new QBibtexAddDialogBase(this, "", true);
connect(add_->addPB, SIGNAL(clicked()), this, SLOT(addDatabase()));
connect(add_->addPB, SIGNAL(clicked()), this, SLOT(addDatabase()));
connect(add_->bibLB, SIGNAL(selected(QListBoxItem *)), this, SLOT(addDatabase()));
connect(add_->bibLB, SIGNAL(selected(QListBoxItem *)), add_, SLOT(accept()));
connect(add_->bibLB, SIGNAL(currentChanged(QListBoxItem *)), this, SLOT(availableChanged()));
connect(add_->browsePB, SIGNAL(clicked()), this, SLOT(browseBibPressed()));
Qt2BC * bcview = new Qt2BC(add_bc_);
add_bc_.view(bcview);
add_bc_.bp(new OkCancelPolicy);
bcview->setOK(add_->addPB);
bcview->setCancel(add_->closePB);
add_->bibED->setValidator(new PathValidator(false, add_->bibED));
addCheckedLineEdit(add_bc_.view(), add_->bibED, 0);
connect(add_->bibED, SIGNAL(textChanged(const QString&)),
this, SLOT(bibEDChanged()));
connect(add_->addPB, SIGNAL(clicked()),
this, SLOT(addDatabase()));
connect(add_->bibLB, SIGNAL(selected(QListBoxItem *)),
this, SLOT(addDatabase()));
connect(add_->bibLB, SIGNAL(selected(QListBoxItem *)),
add_, SLOT(accept()));
connect(add_->bibLB, SIGNAL(currentChanged(QListBoxItem *)),
this, SLOT(availableChanged()));
connect(add_->browsePB, SIGNAL(clicked()),
this, SLOT(browseBibPressed()));
}
QBibtexDialog::~QBibtexDialog()
{}
void QBibtexDialog::bibEDChanged()
{
// Indicate to the button controller that the contents have
// changed. The actual test of validity is carried out by
// the checkedLineEdit.
add_bc_.valid(true);
}
@ -82,7 +119,7 @@ void QBibtexDialog::browsePressed()
void QBibtexDialog::browseBibPressed()
{
string const file = form_->controller().browseBib("");
string const file = trim(form_->controller().browseBib(""));
if (!file.empty()) {
string const f = ChangeExtension(file, "");
@ -102,16 +139,18 @@ void QBibtexDialog::browseBibPressed()
}
}
void QBibtexDialog::addPressed()
{
add_->exec();
add_bc_.valid(false);
}
void QBibtexDialog::addDatabase()
{
int const sel = add_->bibLB->currentItem();
QString const file = add_->bibED->text();
QString const file = trim(add_->bibED->text());
if (sel < 0 && file.isNull())
return;

View File

@ -13,6 +13,7 @@
#define QBIBTEXDIALOG_H
#include "ui/QBibtexDialogBase.h"
#include "ButtonController.h"
class QBibtexAddDialogBase;
@ -26,6 +27,7 @@ class QBibtexDialog : public QBibtexDialogBase {
public:
QBibtexDialog(QBibtex * form);
~QBibtexDialog();
QBibtexAddDialogBase * add_;
@ -38,12 +40,14 @@ protected slots:
virtual void deletePressed();
virtual void databaseChanged();
virtual void availableChanged();
void bibEDChanged();
protected:
virtual void closeEvent(QCloseEvent * e);
private:
QBibtex * form_;
ButtonController add_bc_;
};
} // namespace frontend

View File

@ -31,6 +31,7 @@
#include "checkedwidgets.h"
#include "lengthcombo.h"
#include "qt_helpers.h"
#include "validators.h"
#include <qlineedit.h>
#include <qpushbutton.h>
@ -320,6 +321,7 @@ void QExternal::build_dialog()
addCheckedLineEdit(bcview(), dialog_->ybED, dialog_->lbLA);
addCheckedLineEdit(bcview(), dialog_->xrED, dialog_->rtLA);
addCheckedLineEdit(bcview(), dialog_->ytED, dialog_->rtLA);
addCheckedLineEdit(bcview(), dialog_->fileED, dialog_->fileLA);
std::vector<string> templates(controller().getTemplates());
@ -343,6 +345,10 @@ void QExternal::build_dialog()
void QExternal::update_contents()
{
PathValidator * path_validator = getPathValidator(dialog_->fileED);
if (path_validator)
path_validator->setChecker(kernel().docType(), lyxrc);
dialog_->tab->setCurrentPage(0);
InsetExternalParams const & params = controller().params();

View File

@ -68,6 +68,8 @@ QExternalDialog::QExternalDialog(QExternal * form)
widthED->setValidator(unsignedLengthValidator(widthED));
heightED->setValidator(unsignedLengthValidator(heightED));
fileED->setValidator(new PathValidator(true, fileED));
}

View File

@ -19,6 +19,7 @@
#include "QGraphicsDialog.h"
#include "Qt2BC.h"
#include "qt_helpers.h"
#include "validators.h"
#include "lengthcommon.h"
#include "lyxrc.h"
@ -114,6 +115,7 @@ void QGraphics::build_dialog()
addCheckedLineEdit(bcview(), dialog_->lbY, dialog_->yL);
addCheckedLineEdit(bcview(), dialog_->rtX, dialog_->xL_2);
addCheckedLineEdit(bcview(), dialog_->rtY, dialog_->yL_2);
addCheckedLineEdit(bcview(), dialog_->filename, dialog_->filenameL);
}
@ -131,6 +133,10 @@ int getItemNo(vector<string> v, string const & s) {
void QGraphics::update_contents()
{
PathValidator * path_validator = getPathValidator(dialog_->filename);
if (path_validator)
path_validator->setChecker(kernel().docType(), lyxrc);
// clear and fill in the comboboxes
vector<string> const bb_units = lyx::frontend::getBBUnits();
dialog_->lbXunit->clear();

View File

@ -58,6 +58,8 @@ QGraphicsDialog::QGraphicsDialog(QGraphics * form)
displayscale->setValidator(new QIntValidator(displayscale));
height->setValidator(unsignedLengthValidator(height));
width->setValidator(unsignedLengthValidator(width));
filename->setValidator(new PathValidator(true, filename));
}

View File

@ -12,8 +12,13 @@
#include "QIncludeDialog.h"
#include "QInclude.h"
#include "checkedwidgets.h"
#include "Qt2BC.h"
#include "qt_helpers.h"
#include "validators.h"
#include "lyxrc.h"
#include "controllers/ControlInclude.h"
@ -45,11 +50,17 @@ void QInclude::build_dialog()
bcview().addReadOnly(dialog_->browsePB);
bcview().addReadOnly(dialog_->visiblespaceCB);
bcview().addReadOnly(dialog_->typeCO);
addCheckedLineEdit(bcview(), dialog_->filenameED, dialog_->filenameLA);
}
void QInclude::update_contents()
{
PathValidator * path_validator = getPathValidator(dialog_->filenameED);
if (path_validator)
path_validator->setChecker(kernel().docType(), lyxrc);
InsetCommandParams const & params = controller().params();
dialog_->filenameED->setText(toqstr(params.getContents()));

View File

@ -12,6 +12,7 @@
#include "QIncludeDialog.h"
#include "QInclude.h"
#include "validators.h"
#include <qpushbutton.h>
#include <qcheckbox.h>
@ -29,6 +30,8 @@ QIncludeDialog::QIncludeDialog(QInclude * form)
form, SLOT(slotOK()));
connect(closePB, SIGNAL(clicked()),
form, SLOT(slotClose()));
filenameED->setValidator(new PathValidator(true, filenameED));
}

View File

@ -1,3 +1,13 @@
2005-05-13 Angus Leeming <leeming@lyx.org>
* checkedwidgets.[Ch] (CheckedPath): new class that determines
whether the input file name is valid or not.
* FormExternal.[Ch]:
* FormGraphics.[Ch]:
* FormInclude.[Ch]: use the new CheckedPath to control the
activation state of the "OK", "Apply" buttons.
2005-05-09 Lars Gullik Bjønnes <larsbj@gullik.net>
* forms/Makefile.am: add a distclean-local target to remove
@ -12,8 +22,8 @@
2005-05-04 Michael Schmitt <michael.schmitt@teststep.org>
* forms/form_preferences.fd: fix capitalization.
* Form*.C: Change dialog titles - harmonize with Qt frontend and
menu entries; fix capitalization; change "citation reference"
* Form*.C: Change dialog titles - harmonize with Qt frontend and
menu entries; fix capitalization; change "citation reference"
to "citation".
* FormTexinfo.C: correct tooltip.

View File

@ -319,7 +319,8 @@ void getExtra(external::ExtraData & data,
typedef FormController<ControlExternal, FormView<FD_external> > base_class;
FormExternal::FormExternal(Dialog & parent)
: base_class(parent, _("External Material"))
: base_class(parent, _("External Material")),
file_checker_(0)
{}
@ -366,6 +367,8 @@ void FormExternal::build()
bcview().addReadOnly(options_->choice_option);
bcview().addReadOnly(options_->input_option);
file_checker_ = &addCheckedPath(bcview(), true, file_->input_file);
// initial setting
// addCheckedPositiveFloat(bcview(), scale_->input_width);
// As I haven't written addCheckedPositiveFloat, we default to
@ -464,6 +467,8 @@ void FormExternal::build()
void FormExternal::update()
{
file_checker_->setChecker(kernel().docType(), lyxrc);
fl_set_folder_bynumber(dialog_->tabfolder, 1);
InsetExternalParams const & params = controller().params();

View File

@ -20,6 +20,7 @@
namespace lyx {
namespace frontend {
class CheckedPath;
class ControlExternal;
struct FD_external;
struct FD_external_file;
@ -67,6 +68,9 @@ private:
void updateComboChange();
void widthUnitChanged();
// Accessor to checker owned by the button controller.
CheckedPath * file_checker_;
MapType extra_;
TabMap tabmap_;

View File

@ -75,7 +75,8 @@ bool const scalableTabfolders = true;
typedef FormController<ControlGraphics, FormView<FD_graphics> > base_class;
FormGraphics::FormGraphics(Dialog & parent)
: base_class(parent, _("Graphics"), scalableTabfolders)
: base_class(parent, _("Graphics"), scalableTabfolders),
file_checker_(0)
{}
@ -110,6 +111,8 @@ void FormGraphics::build()
bcview().addReadOnly(file_->check_draft);
bcview().addReadOnly(file_->check_nounzip);
file_checker_ = &addCheckedPath(bcview(), true, file_->input_filename);
// Check validity of "length + unit" input.
addCheckedGlueLength(bcview(), file_->input_width);
addCheckedGlueLength(bcview(), file_->input_height);
@ -431,7 +434,10 @@ void FormGraphics::apply()
}
void FormGraphics::update() {
void FormGraphics::update()
{
file_checker_->setChecker(kernel().docType(), lyxrc);
// Update dialog with details from inset
InsetGraphicsParams & igp = controller().params();

View File

@ -20,6 +20,7 @@
namespace lyx {
namespace frontend {
class CheckedPath;
class ControlGraphics;
struct FD_graphics;
struct FD_graphics_file;
@ -49,6 +50,9 @@ private:
/// Filter the inputs on callback from xforms
virtual ButtonPolicy::SMInput input(FL_OBJECT *, long);
// Accessor to checker owned by the button controller.
CheckedPath * file_checker_;
/// Real GUI implementation.
boost::scoped_ptr<FD_graphics_file> file_;
///

View File

@ -16,10 +16,13 @@
#include "ControlInclude.h"
#include "forms/form_include.h"
#include "checkedwidgets.h"
#include "Tooltips.h"
#include "xforms_helpers.h" // setEnabled
#include "xformsBC.h"
#include "lyxrc.h"
#include "support/lstrings.h" // strip
#include "lyx_forms.h"
@ -35,7 +38,8 @@ namespace frontend {
typedef FormController<ControlInclude, FormView<FD_include> > base_class;
FormInclude::FormInclude(Dialog & parent)
: base_class(parent, _("Child Document"))
: base_class(parent, _("Child Document")),
file_checker_(0)
{}
@ -58,6 +62,8 @@ void FormInclude::build()
bcview().addReadOnly(dialog_->radio_useinclude);
bcview().addReadOnly(dialog_->radio_verbatim);
file_checker_ = &addCheckedPath(bcview(), true, dialog_->input_filename);
type_.init(dialog_->radio_useinput, ControlInclude::INPUT);
type_.init(dialog_->radio_useinclude, ControlInclude::INCLUDE);
type_.init(dialog_->radio_verbatim, ControlInclude::VERBATIM);
@ -84,6 +90,8 @@ void FormInclude::build()
void FormInclude::update()
{
file_checker_->setChecker(kernel().docType(), lyxrc);
string const filename = controller().params().getContents();
string const cmdname = controller().params().getCmdName();
bool const preview = static_cast<bool>((controller().params().preview()));

View File

@ -19,6 +19,7 @@
namespace lyx {
namespace frontend {
class CheckedPath;
class ControlInclude;
struct FD_include;
@ -39,6 +40,9 @@ private:
/// Filter the inputs on callback from xforms
virtual ButtonPolicy::SMInput input(FL_OBJECT *, long);
// Accessor to checker owned by the button controller.
CheckedPath * file_checker_;
/// include type
RadioButtonGroup type_;
};

View File

@ -13,32 +13,53 @@
#include "checkedwidgets.h"
#include "xforms_helpers.h"
#include "gettext.h"
#include "lyxgluelength.h"
#include "lyxrc.h"
#include "frontends/Alert.h"
#include "frontends/controllers/Kernel.h"
#include "support/lstrings.h"
#include "lyx_forms.h"
#include <sstream>
using lyx::support::isStrDbl;
using std::string;
namespace lyx {
using support::isStrDbl;
namespace frontend {
void addCheckedLyXLength(BCView & bcview,
FL_OBJECT * input, FL_OBJECT * label)
CheckedLyXLength &
addCheckedLyXLength(BCView & bcview, FL_OBJECT * input, FL_OBJECT * label)
{
bcview.addCheckedWidget(new CheckedLyXLength(input, label));
CheckedLyXLength * cw(new CheckedLyXLength(input, label));
bcview.addCheckedWidget(cw);
return *cw;
}
void addCheckedGlueLength(BCView & bcview,
FL_OBJECT * input, FL_OBJECT * label)
CheckedGlueLength &
addCheckedGlueLength(BCView & bcview, FL_OBJECT * input, FL_OBJECT * label)
{
bcview.addCheckedWidget(new CheckedGlueLength(input, label));
CheckedGlueLength * cw(new CheckedGlueLength(input, label));
bcview.addCheckedWidget(cw);
return *cw;
}
CheckedPath &
addCheckedPath(BCView & bcview, bool acceptable_if_empty,
FL_OBJECT * input, FL_OBJECT * label)
{
CheckedPath * cw(new CheckedPath(acceptable_if_empty, input, label));
bcview.addCheckedWidget(cw);
return *cw;
}
@ -107,5 +128,87 @@ bool CheckedGlueLength::check() const
return valid;
}
CheckedPath::CheckedPath(bool acceptable_if_empty,
FL_OBJECT * input, FL_OBJECT * label)
: input_(input), label_(label ? label : input),
acceptable_if_empty_(acceptable_if_empty),
latex_doc_(false),
tex_allows_spaces_(false)
{}
void CheckedPath::setChecker(lyx::frontend::KernelDocType const & type,
LyXRC const & lyxrc)
{
latex_doc_ = type == lyx::frontend::Kernel::LATEX;
tex_allows_spaces_ = lyxrc.tex_allows_spaces;
}
namespace {
string const printable_list(string const & invalid_chars)
{
std::ostringstream ss;
string::const_iterator const begin = invalid_chars.begin();
string::const_iterator const end = invalid_chars.end();
string::const_iterator it = begin;
for (; it != end; ++it) {
if (it != begin)
ss << ", ";
if (*it == ' ')
ss << _("space");
else
ss << *it;
}
return ss.str();
}
} // namespace anon
bool CheckedPath::check() const
{
if (!latex_doc_) {
setWidget(true, input_, label_);
return true;
}
if (!isActive(input_)) {
setWidget(true, input_, label_);
return true;
}
string const text = getString(input_);
if (text.empty()) {
setWidget(acceptable_if_empty_, input_, label_);
return acceptable_if_empty_;
}
string invalid_chars("#$%{}()[]:\"^");
if (!tex_allows_spaces_)
invalid_chars += ' ';
bool valid = true;
if (text.find_first_of(invalid_chars) != string::npos) {
static int counter = 0;
if (counter == 0) {
Alert::error(_("Invalid filename"),
_("LyX does not provide LateX support for file names containing any of these characters:\n") +
printable_list(invalid_chars));
}
++counter;
valid = false;
}
// set the color of label and input widget
setWidget(valid, input_, label_);
return valid;
}
} // namespace frontend
} // namespace lyx

View File

@ -18,11 +18,22 @@
namespace lyx {
namespace frontend {
void addCheckedLyXLength(BCView & bcview,
FL_OBJECT * input, FL_OBJECT * label = 0);
class CheckedLyXLength;
class CheckedGlueLength;
class CheckedPath;
//
CheckedLyXLength &
addCheckedLyXLength(BCView & bcview, FL_OBJECT * input, FL_OBJECT * label = 0);
CheckedGlueLength &
addCheckedGlueLength(BCView & bcview, FL_OBJECT * input, FL_OBJECT * label = 0);
CheckedPath &
addCheckedPath(BCView & bcview, bool acceptable_if_empty,
FL_OBJECT * input, FL_OBJECT * label = 0);
void addCheckedGlueLength(BCView & bcview,
FL_OBJECT * input, FL_OBJECT * label = 0);
class CheckedLyXLength : public CheckedWidget {
public:
@ -62,4 +73,49 @@ private:
} // namespace frontend
} // namespace lyx
// Forward declarations
class LyXRC;
namespace lyx {
namespace frontend {
class KernelDocType;
class CheckedPath : public CheckedWidget {
public:
/** The label widget's label will be turned red if input
* does not make a valid file path.
* If label == 0, then the label of input will be used.
* If @c acceptable_if_empty is @c true then an empty path
* is regarded as acceptable.
*/
CheckedPath(bool acceptable_if_empty,
FL_OBJECT * input, FL_OBJECT * label = 0);
/** Define now to perform the check.
* @param doc_type checks are activated only for @c LATEX docs.
* @param lyxrc contains a @c tex_allows_spaces member that
* is used to define what is legal.
*/
void setChecker(lyx::frontend::KernelDocType const & doc_type,
LyXRC const & lyxrc);
private:
///
virtual bool check() const;
///
FL_OBJECT * input_;
FL_OBJECT * label_;
bool acceptable_if_empty_;
bool latex_doc_;
bool tex_allows_spaces_;
};
} // namespace frontend
} // namespace lyx
#endif // CHECKEDWIDGETS_H