]> git.lyx.org Git - features.git/blob - src/frontends/qt4/GuiEmbeddedFiles.cpp
e0f3c6b050a734e4a8831960a293f5d3b42d8a9a
[features.git] / src / frontends / qt4 / GuiEmbeddedFiles.cpp
1 /**
2  * \file GuiEmbeddedFiles.cpp
3  * This file is part of LyX, the document processor.
4  * Licence details can be found in the file COPYING.
5  *
6  * \author Bo Peng
7  *
8  * Full author contact details are available in file CREDITS.
9  */
10
11 #include <config.h>
12
13 #include "GuiEmbeddedFiles.h"
14
15 #include "Buffer.h"
16
17 #include "FuncRequest.h"
18 #include "gettext.h"
19 #include "debug.h"
20 #include "Format.h"
21 #include "LyXRC.h"
22
23 #include "frontend_helpers.h"
24 #include "frontends/LyXView.h"
25
26 #include "support/FileFilterList.h"
27
28 using std::string;
29
30
31 namespace lyx {
32 namespace frontend {
33
34 using support::FileFilterList;
35
36 EmbeddedFilesWidget::EmbeddedFilesWidget
37                 (GuiEmbeddedFiles & controller)
38         : controller_(controller)
39 {
40         setupUi(this);
41         setWindowTitle("LyX: " + qt_("Embedded Files"));
42
43         // FIXME: Temporary icons.
44         selectPB->setIcon(QIcon(":/images/tabular-feature_set-all-lines.png"));
45         unselectPB->setIcon(QIcon(":/images/tabular-feature_unset-all-lines.png"));
46         addPB->setIcon(QIcon(":/images/file-open.png"));
47         extractPB->setIcon(QIcon(":/images/depth-decrement.png"));
48         updatePB->setIcon(QIcon(":/images/depth-increment.png"));
49
50         updateView();
51 }
52
53
54 void EmbeddedFilesWidget::on_filesLW_itemChanged(QListWidgetItem* item)
55 {
56         EmbeddedFiles & files = controller_.embeddedFiles();
57         if (item->checkState() == Qt::Checked) {
58                 if (files[filesLW->row(item)].embedded())
59                         return;
60                 // this should not be needed after EmbeddedFiles are updated correctly.
61                 files.update();
62                 controller_.setEmbed(files[filesLW->row(item)], true, files.enabled());
63         } else {
64                 if (!files[filesLW->row(item)].embedded())
65                         return;
66                 // this should not be needed after EmbeddedFiles are updated correctly.
67                 files.update();
68                 controller_.setEmbed(files[filesLW->row(item)], false, files.enabled());
69         }
70 }
71
72
73 void EmbeddedFilesWidget::on_filesLW_itemSelectionChanged()
74 {
75         if (controller_.isReadonly())
76                 return;
77
78         QList<QListWidgetItem *> selection = filesLW->selectedItems();
79
80         if (selection.empty()) {
81                 fullpathLE->setEnabled(false);
82                 selectPB->setEnabled(false);
83                 unselectPB->setEnabled(false);
84                 extractPB->setEnabled(false);
85                 updatePB->setEnabled(false);
86                 return;
87         }
88         
89         fullpathLE->setEnabled(selection.size() == 1);
90
91         // try to find a common embedding status
92         bool hasSelected = false;
93         bool hasUnselected = false;
94         QList<QListWidgetItem*>::iterator it = selection.begin(); 
95         QList<QListWidgetItem*>::iterator it_end = selection.end(); 
96         for (; it != it_end; ++it) {
97                 if ((*it)->checkState() == Qt::Checked)
98                         hasSelected = true;
99                 else
100                         hasUnselected = true;
101         }
102         selectPB->setEnabled(hasUnselected);
103         unselectPB->setEnabled(hasSelected);
104 }
105
106
107 void EmbeddedFilesWidget::on_filesLW_itemClicked(QListWidgetItem* item)
108 {
109         EmbeddedFiles & files = controller_.embeddedFiles();
110         int idx = filesLW->row(item);
111         fullpathLE->setText(toqstr(files[idx].absFilename()));
112         if (files[idx].refCount() > 1) {
113                 // if multiple insets are referred, click again will move
114                 // to another inset
115                 int k = item->data(Qt::UserRole).toInt();
116                 controller_.goTo(files[idx], k);
117                 k = (k + 1) % files[idx].refCount();
118                 item->setData(Qt::UserRole, k);
119                 // update label
120                 QString label = toqstr(files[idx].inzipName())
121                         + QString(" (%1/%2)").arg(k + 1).arg(files[idx].refCount());
122                 item->setText(label);
123         } else if (files[idx].refCount() == 1)
124                 controller_.goTo(files[idx], 0);
125 }
126
127
128 void EmbeddedFilesWidget::on_filesLW_itemDoubleClicked(QListWidgetItem* item)
129 {
130         EmbeddedFiles & files = controller_.embeddedFiles();
131         controller_.view(files[filesLW->row(item)]);
132 }
133
134
135 void EmbeddedFilesWidget::updateView()
136 {
137         bool readOnly = controller_.isReadonly();
138         fullpathLE->setEnabled(!readOnly);
139         selectPB->setEnabled(!readOnly);
140         unselectPB->setEnabled(!readOnly);
141         addPB->setEnabled(!readOnly);
142         extractPB->setEnabled(!readOnly);
143         updatePB->setEnabled(!readOnly);
144         enableCB->setEnabled(!readOnly);
145         
146         filesLW->clear();
147         EmbeddedFiles const & files = controller_.embeddedFiles();
148         enableCB->setCheckState(files.enabled() ? Qt::Checked : Qt::Unchecked);
149         EmbeddedFiles::EmbeddedFileList::const_iterator it = files.begin();
150         EmbeddedFiles::EmbeddedFileList::const_iterator it_end = files.end();
151         for (; it != it_end; ++it) {
152                 QString label = toqstr(it->inzipName());
153                 if (it->refCount() > 1)
154                         label += " (1/" + QString::number(it->refCount()) + ")";
155                 QListWidgetItem * item = new QListWidgetItem(label);
156                 Qt::ItemFlags flag = Qt::ItemIsSelectable;
157                 if (!readOnly)
158                         flag |= Qt::ItemIsUserCheckable;
159                 if (it->valid())
160                         flag |= Qt::ItemIsEnabled;
161                 item->setFlags(flag);
162                 if(it->embedded())
163                         item->setCheckState(Qt::Checked);
164                 else
165                         item->setCheckState(Qt::Unchecked);
166                 // index of the currently used ParConstIterator
167                 item->setData(Qt::UserRole, 0);
168                 filesLW->addItem(item);
169         }
170 }
171
172
173 void EmbeddedFilesWidget::on_selectPB_clicked()
174 {
175         EmbeddedFiles & files = controller_.embeddedFiles();
176         // this should not be needed after EmbeddedFiles are updated correctly.
177         files.update();
178         QList<QListWidgetItem *> selection = filesLW->selectedItems();
179         for (QList<QListWidgetItem*>::iterator it = selection.begin(); 
180                 it != selection.end(); ++it) {
181                 (*it)->setCheckState(Qt::Checked);
182                 controller_.setEmbed(files[filesLW->row(*it)], true, files.enabled());
183         }
184         controller_.dispatchMessage("Embedding files");
185 }
186
187
188 void EmbeddedFilesWidget::on_unselectPB_clicked()
189 {
190         EmbeddedFiles & files = controller_.embeddedFiles();
191         // this should not be needed after EmbeddedFiles are updated correctly.
192         files.update();
193         QList<QListWidgetItem *> selection = filesLW->selectedItems();
194         for (QList<QListWidgetItem*>::iterator it = selection.begin(); 
195                 it != selection.end(); ++it) {
196                 (*it)->setCheckState(Qt::Checked);
197                 controller_.setEmbed(files[filesLW->row(*it)], false, files.enabled());
198         }
199         controller_.dispatchMessage("Stop embedding files");
200 }
201
202
203 void EmbeddedFilesWidget::on_addPB_clicked()
204 {
205         if (controller_.browseAndAddFile())
206                 updateView();
207 }
208
209
210 void EmbeddedFilesWidget::on_extractPB_clicked()
211 {
212         EmbeddedFiles const & files = controller_.embeddedFiles();
213         QList<QListWidgetItem *> selection = filesLW->selectedItems();
214         for (QList<QListWidgetItem*>::iterator it = selection.begin(); 
215                 it != selection.end(); ++it)
216                 controller_.extract(files[filesLW->row(*it)]);
217         // FIXME: collect extraction status and display a dialog
218         controller_.dispatchMessage("Extract embedded files");
219 }
220
221
222 void EmbeddedFilesWidget::on_updatePB_clicked()
223 {
224         EmbeddedFiles const & files = controller_.embeddedFiles();
225         QList<QListWidgetItem *> selection = filesLW->selectedItems();
226         for (QList<QListWidgetItem*>::iterator it = selection.begin(); 
227                 it != selection.end(); ++it)
228                 controller_.update(files[filesLW->row(*it)]);
229         // FIXME: collect update status and display a dialog
230         controller_.dispatchMessage("Update embedded files from external file");
231 }
232
233
234
235 void EmbeddedFilesWidget::on_enableCB_toggled(bool enable)
236 {
237         controller_.setEmbedding(enable);
238 }
239
240
241
242 GuiEmbeddedFiles::GuiEmbeddedFiles(GuiViewBase & parent,
243         Qt::DockWidgetArea area, Qt::WindowFlags flags)
244         : DockView(parent, "embedded", area, flags)
245 {
246         widget_ = new EmbeddedFilesWidget(*this);
247         setWidget(widget_);
248         setWindowTitle(widget_->windowTitle());
249 }
250
251
252 void GuiEmbeddedFiles::updateView()
253 {
254         widget_->updateView();
255 }
256
257
258 EmbeddedFiles & GuiEmbeddedFiles::embeddedFiles()
259 {
260         return buffer().embeddedFiles();
261 }
262
263
264 bool GuiEmbeddedFiles::initialiseParams(string const &)
265 {
266         return true;
267 }
268
269
270 void GuiEmbeddedFiles::updateEmbeddedFiles()
271 {
272         // copy buffer embeddedFiles to a local copy
273         buffer().embeddedFiles().update();
274         buffer().embeddingChanged();
275 }
276
277
278 void GuiEmbeddedFiles::dispatchMessage(string const & msg)
279 {
280         // FIXME: the right thing to do? QT guys?
281         // lyx view will only be updated if we do something to the main window. :-)
282         dispatch(FuncRequest(LFUN_MESSAGE, msg));
283 }
284
285
286 bool GuiEmbeddedFiles::isReadonly()
287 {
288         return buffer().isReadonly();
289 }
290
291
292 void GuiEmbeddedFiles::setEmbedding(bool enable)
293 {
294         if (embeddedFiles().enabled() == enable)
295                 return;
296         embeddedFiles().enable(enable);
297         buffer().markDirty();
298         if (enable)
299                 dispatchMessage("Stop saving in bundled format.");
300         else
301                 dispatchMessage("Save in bundled format.");
302 }
303
304
305 void GuiEmbeddedFiles::goTo(EmbeddedFile const & item, int idx)
306 {
307         BOOST_ASSERT(idx < item.refCount());
308         item.saveBookmark(&buffer(), idx);
309         lyxview().dispatch(FuncRequest(LFUN_BOOKMARK_GOTO, "0"));
310 }
311
312
313 void GuiEmbeddedFiles::view(EmbeddedFile const & item)
314 {
315         formats.view(buffer(), item, formats.getFormatFromFile(item));
316 }
317
318
319 void GuiEmbeddedFiles::setEmbed(EmbeddedFile & item, bool embed, bool update)
320 {
321         if (item.embedded() == embed)
322                 return;
323         item.setEmbed(embed);
324         if (update) {
325                 if (embed)
326                         item.updateFromExternalFile(&buffer());
327                 else
328                         item.extract(&buffer());
329                 item.updateInsets(&buffer());
330                 // FIXME: unless we record the type of file item, we will
331                 // need to update all possible dialogs (bibtex etc).
332                 updateDialog("graphics");
333         }
334         if (embed)
335                 dispatchMessage("Embed file " + item.outputFilename(buffer().filePath()));
336         else
337                 dispatchMessage("Stop embedding file " + item.outputFilename(buffer().filePath()));
338         buffer().markDirty();
339 }
340
341
342 bool GuiEmbeddedFiles::browseAndAddFile()
343 {
344         std::pair<docstring, docstring> dir1(_("Documents|#o#O"),
345                                   from_utf8(lyxrc.document_path));
346         FileFilterList const filter(_("All file (*.*)"));
347         docstring const file = browseRelFile(docstring(), from_utf8(bufferFilepath()),
348                              _("Select a file to embed"),
349                              filter, false, dir1);
350         if (!file.empty()) {
351                 EmbeddedFile & ef = embeddedFiles().registerFile(to_utf8(file), true);
352                 if (embeddedFiles().enabled())
353                         ef.updateFromExternalFile(&buffer());
354                 buffer().markDirty();
355                 dispatchMessage("Add an embedded file" + to_utf8(file));
356                 return true;
357         }
358         return false;
359 }
360
361
362 bool GuiEmbeddedFiles::extract(EmbeddedFile const & item)
363 {
364         if (item.embedded())
365                 return item.extract(&buffer());
366         else
367                 return false;
368 }
369
370
371 bool GuiEmbeddedFiles::update(EmbeddedFile const & item)
372 {
373         if (item.embedded())
374                 return item.updateFromExternalFile(&buffer());
375         else
376                 return false;
377 }
378
379
380 Dialog * createGuiEmbeddedFiles(LyXView & lv)
381 {
382         GuiViewBase & guiview = static_cast<GuiViewBase &>(lv);
383 #ifdef Q_WS_MACX
384         // On Mac show as a drawer at the right
385         return new GuiEmbeddedFiles(guiview, Qt::RightDockWidgetArea, Qt::Drawer);
386 #else
387         return new GuiEmbeddedFiles(guiview, Qt::RightDockWidgetArea);
388 #endif
389 }
390
391
392 } // namespace frontend
393 } // namespace lyx
394
395 #include "GuiEmbeddedFiles_moc.cpp"