]> git.lyx.org Git - lyx.git/blob - src/frontends/qt4/GuiTexinfo.cpp
Fix a crash following the input of an invalid paragraph separation value in the docum...
[lyx.git] / src / frontends / qt4 / GuiTexinfo.cpp
1 /**
2  * \file GuiTexinfo.cpp
3  * This file is part of LyX, the document processor.
4  * Licence details can be found in the file COPYING.
5  *
6  * \author Edwin Leuven
7  * \author Herbert Voß
8  *
9  * Full author contact details are available in file CREDITS.
10  */
11
12 #include <config.h>
13
14 #include "GuiTexinfo.h"
15
16 #include "FuncRequest.h"
17 #include "support/debug.h"
18
19 #include "support/filetools.h"
20 #include "support/FileName.h"
21 #include "support/lstrings.h"
22
23 #include "qt_helpers.h"
24
25 #include <QCloseEvent>
26 #include <QCheckBox>
27 #include <QListWidget>
28 #include <QPushButton>
29
30 #include <fstream>
31 #include <algorithm>
32
33 using namespace std;
34 using namespace lyx::support;
35
36 namespace lyx {
37 namespace frontend {
38
39
40 static string texFileFromList(string const & file, string const & type)
41 {
42         string file_ = file;
43         // do we need to add the suffix?
44         if (!(getExtension(file) == type))
45                 file_ += '.' + type;
46
47         lyxerr << "Searching for file " << file_ << endl;
48
49         string lstfile = type + "Files.lst";
50         if (type == "cls")
51                 lstfile = "clsFiles.lst";
52         else if (type == "sty")
53                 lstfile = "styFiles.lst";
54         else if (type == "bst")
55                 lstfile = "bstFiles.lst";
56         else if (type == "bib")
57                 lstfile = "bibFiles.lst";
58         FileName const abslstfile = libFileSearch(string(), lstfile);
59         if (abslstfile.empty()) {
60                 lyxerr << "File `'" << lstfile << "' not found." << endl;
61                 return string();
62         }
63         // FIXME UNICODE
64         string const allClasses = to_utf8(abslstfile.fileContents("UTF-8"));
65         int entries = 0;
66         string classfile = token(allClasses, '\n', entries);
67         int count = 0;
68         while ((!contains(classfile, file) ||
69                 (onlyFilename(classfile) != file)) &&
70                 (++count < 1000)) {
71                 classfile = token(allClasses, '\n', ++entries);
72         }
73
74         // now we have filename with full path
75         lyxerr << "with full path: " << classfile << endl;
76
77         return classfile;
78 }
79
80
81 GuiTexInfo::GuiTexInfo(GuiView & lv)
82         : GuiDialog(lv, "texinfo", qt_("TeX Information"))
83 {
84         setupUi(this);
85
86         warningPosted = false;
87         activeStyle = ClsType;
88
89         connect(closePB, SIGNAL(clicked()), this, SLOT(slotClose()));
90
91         connect(viewPB, SIGNAL(clicked()), this, SLOT(viewClicked()));
92         connect(whatStyleCO, SIGNAL(activated(QString)),
93                 this, SLOT(enableViewPB()));
94         connect(whatStyleCO, SIGNAL(activated(int)), this, SLOT(updateView()));
95         connect(pathCB, SIGNAL(stateChanged(int)), this, SLOT(updateView()));
96         connect(rescanPB, SIGNAL(clicked()), this, SLOT(enableViewPB()));
97         connect(rescanPB, SIGNAL(clicked()), this, SLOT(rescanClicked()));
98         connect(fileListLW, SIGNAL(itemClicked(QListWidgetItem *)),
99                 this, SLOT(enableViewPB()));
100         connect(fileListLW, SIGNAL(itemSelectionChanged()),
101                 this, SLOT(enableViewPB()));
102
103         updateStyles(ClsType);
104
105         bc().setPolicy(ButtonPolicy::OkCancelPolicy);
106         bc().setCancel(closePB);
107 }
108
109
110 void GuiTexInfo::change_adaptor()
111 {
112         changed();
113 }
114
115
116 void GuiTexInfo::closeEvent(QCloseEvent * e)
117 {
118         slotClose();
119         e->accept();
120 }
121
122
123 void GuiTexInfo::rescanClicked()
124 {
125         // build new *Files.lst
126         rescanTexStyles();
127         updateStyles();
128         enableViewPB();
129 }
130
131
132 void GuiTexInfo::viewClicked()
133 {
134         size_t const fitem = fileListLW->currentRow();
135         vector<string> const & data = texdata_[activeStyle];
136         string file = data[fitem];
137         if (!pathCB->isChecked())
138                 file = texFileFromList(data[fitem], fileType(activeStyle));
139         viewFile(file);
140 }
141
142
143 void GuiTexInfo::updateView()
144 {
145         // takes advantage of enum order
146         updateStyles(static_cast<TexFileType>(whatStyleCO->currentIndex()));
147         enableViewPB();
148 }
149
150
151 void GuiTexInfo::enableViewPB()
152 {
153         viewPB->setEnabled(fileListLW->currentRow() > -1);
154 }
155
156
157 void GuiTexInfo::updateStyles(TexFileType type)
158 {
159         ContentsType & data = texdata_[type];
160
161         static string filenames[] = { "clsFile.lst", "styFiles.lst", "bstFiles.lst" };
162         string filename = filenames[type];
163
164         getTexFileList(filename, data);
165         if (data.empty()) {
166                 // build filelists of all availabe bst/cls/sty-files.
167                 // Done through kpsewhich and an external script,
168                 // saved in *Files.lst
169                 rescanTexStyles();
170                 getTexFileList(filename, data);
171         }
172         bool const withFullPath = pathCB->isChecked();
173         if (withFullPath)
174                 return;
175         vector<string>::iterator it1  = data.begin();
176         vector<string>::iterator end1 = data.end();
177         for (; it1 != end1; ++it1)
178                 *it1 = onlyFilename(*it1);
179
180         // sort on filename only (no path)
181         sort(data.begin(), data.end());
182
183         fileListLW->clear();
184         ContentsType::const_iterator it  = data.begin();
185         ContentsType::const_iterator end = data.end();
186         for (; it != end; ++it)
187                 fileListLW->addItem(toqstr(*it));
188
189         activeStyle = type;
190 }
191
192
193 void GuiTexInfo::updateStyles()
194 {
195         updateStyles(activeStyle);
196 }
197
198
199 void GuiTexInfo::viewFile(string const & filename) const
200 {
201         dispatch(FuncRequest(LFUN_DIALOG_SHOW, "file " + filename));
202 }
203
204
205 /// get a class with full path from the list
206 string GuiTexInfo::classOptions(string const & classname) const
207 {
208         FileName const filename(texFileFromList(classname, "cls"));
209         if (filename.empty())
210                 return string();
211         string optionList;
212         ifstream is(filename.toFilesystemEncoding().c_str());
213         while (is) {
214                 string s;
215                 is >> s;
216                 if (contains(s, "DeclareOption")) {
217                         s = s.substr(s.find("DeclareOption"));
218                         s = split(s, '{');              // cut front
219                         s = token(s, '}', 0);           // cut end
220                         optionList += (s + '\n');
221                 }
222         }
223         return optionList;
224 }
225
226
227 string GuiTexInfo::fileType(TexFileType type) const
228 {
229         // takes advantage of enum order
230         static string const ext[] = { "cls", "sty", "bst" };
231         return ext[type];
232 }
233
234
235 Dialog * createGuiTexInfo(GuiView & lv) { return new GuiTexInfo(lv); }
236
237
238 } // namespace frontend
239 } // namespace lyx
240
241
242 #include "GuiTexinfo_moc.cpp"