3 * This file is part of LyX, the document processor.
4 * Licence details can be found in the file COPYING.
6 * \author Vincent van Ravesteijn
8 * Full author contact details are available in file CREDITS.
13 #include "GuiCompare.h"
15 #include "GuiApplication.h"
18 #include "BufferView.h"
19 #include "BufferList.h"
20 #include "buffer_funcs.h"
21 #include "ColorCache.h"
23 #include "FuncRequest.h"
26 #include "qt_helpers.h"
28 #include "frontends/alert.h"
30 #include "support/debug.h"
31 #include "support/filetools.h"
32 #include "support/FileName.h"
33 #include "support/gettext.h"
35 #include <QDialogButtonBox>
40 using namespace lyx::support;
46 GuiCompare::GuiCompare(GuiView & lv)
47 : GuiDialog(lv, "compare", qt_("Compare LyX files")),
48 compare_(0), dest_buffer_(0), old_buffer_(0), new_buffer_(0)
51 setModal(Qt::WindowModal);
53 connect(buttonBox, SIGNAL(clicked(QAbstractButton *)),
54 this, SLOT(slotButtonBox(QAbstractButton *)));
56 connect(newFilePB, SIGNAL(clicked()), this, SLOT(selectNewFile()));
57 connect(oldFilePB, SIGNAL(clicked()), this, SLOT(selectOldFile()));
59 connect(newFileCB, SIGNAL(currentIndexChanged(int)),
60 this, SLOT(changeAdaptor()));
61 connect(newFileCB, SIGNAL(editTextChanged(const QString &)),
62 this, SLOT(changeAdaptor()));
63 connect(oldFileCB, SIGNAL(currentIndexChanged(int)),
64 this, SLOT(changeAdaptor()));
65 connect(oldFileCB, SIGNAL(editTextChanged(const QString &)),
66 this, SLOT(changeAdaptor()));
68 newSettingsRB->setChecked(true);
69 trackingCB->setChecked(true);
71 buttonBox->button(QDialogButtonBox::Ok)->setCursor(Qt::ArrowCursor);
73 bc().setPolicy(ButtonPolicy::OkApplyCancelPolicy);
74 bc().setOK(buttonBox->button(QDialogButtonBox::Ok));
77 GuiCompare::~GuiCompare()
83 void GuiCompare::closeEvent(QCloseEvent *)
89 void GuiCompare::changeAdaptor()
95 bool GuiCompare::isValid()
97 bool const valid = !newFileCB->currentText().isEmpty()
98 && !oldFileCB->currentText().isEmpty();
103 void GuiCompare::updateContents()
105 if (compare_ && compare_->isRunning())
108 QString restore_filename1 = newFileCB->currentText();
109 QString restore_filename2 = oldFileCB->currentText();
112 progressBar->setValue(0);
113 statusBar->clearMessage();
114 BufferList::iterator it = theBufferList().begin();
115 BufferList::iterator const end = theBufferList().end();
116 for (; it != end; ++it) {
117 QString filename = toqstr((*it)->absFileName());
118 newFileCB->addItem(filename);
119 oldFileCB->addItem(filename);
121 if (!restore_filename1.isEmpty())
122 newFileCB->setEditText(restore_filename1);
123 else if (lyxview().documentBufferView())
124 newFileCB->setEditText(toqstr(buffer().absFileName()));
126 if (!restore_filename2.isEmpty())
127 oldFileCB->setEditText(restore_filename2);
129 oldFileCB->clearEditText();
132 bc().setValid(isValid());
138 void GuiCompare::selectNewFile()
140 QString name = browse(newFileCB->currentText());
142 newFileCB->setEditText(name);
147 void GuiCompare::selectOldFile()
149 QString name = browse(oldFileCB->currentText());
151 oldFileCB->setEditText(name);
156 QString GuiCompare::browse(QString const & in_name) const
158 QString const title = qt_("Select document");
160 QStringList const & filters = fileFilters(qt_("LyX Documents (*.lyx)"));
163 if (lyxview().documentBufferView()) {
164 QString path = bufferFilePath();
165 filename = browseRelToParent(in_name, path, title, filters, false,
166 qt_("D&ocuments"), toqstr(lyxrc.document_path));
168 QString path = toqstr(lyxrc.document_path);
169 QString rel_filename = browseRelToParent(in_name, path, title, filters, false,
170 qt_("D&ocuments"), toqstr(lyxrc.document_path));
171 filename = makeAbsPath(rel_filename, path);
177 void GuiCompare::enableControls(bool enable)
179 // Set the hourglass cursor for the dialog, but
180 // never for the cancel button.
181 setCursor(enable ? Qt::ArrowCursor : Qt::WaitCursor);
183 newFileLA->setEnabled(enable);
184 newFilePB->setEnabled(enable);
185 newFileCB->setEnabled(enable);
186 oldFileLA->setEnabled(enable);
187 oldFilePB->setEnabled(enable);
188 oldFileCB->setEnabled(enable);
189 buttonBox->button(QDialogButtonBox::Ok)->setEnabled(enable);
190 groupBox->setEnabled(enable);
191 progressBar->setEnabled(!enable);
194 buttonBox->button(QDialogButtonBox::Cancel)->setText(qt_("Close"));
196 buttonBox->button(QDialogButtonBox::Cancel)->setText(qt_("Cancel"));
200 void GuiCompare::error()
202 Alert::error(_("Error"), _("Error while comparing documents."));
206 void GuiCompare::finished(bool aborted)
208 enableControls(true);
217 dest_buffer_->markClean();
218 theBufferList().release(dest_buffer_);
220 progressBar->setValue(0);
221 statusBar->showMessage(qt_("Aborted"), 5000);
226 dispatch(FuncRequest(LFUN_BUFFER_SWITCH,
227 dest_buffer_->absFileName()));
228 if (trackingCB->isChecked()) {
229 dispatch(FuncRequest(LFUN_CHANGES_OUTPUT));
230 dispatch(FuncRequest(LFUN_CHANGES_TRACK));
233 statusBar->showMessage(qt_("Finished"), 5000);
238 void GuiCompare::progress(int val)
240 progressBar->setValue(progressBar->value() + val);
244 void GuiCompare::progressMax(int max) const
246 progressBar->setMaximum(max);
250 void GuiCompare::setStatusMessage(QString const & msg)
252 statusBar->showMessage(msg);
256 void GuiCompare::slotOK()
258 enableControls(false);
264 void GuiCompare::slotCancel()
266 if (compare_ && compare_->isRunning()) {
267 statusBar->showMessage(qt_("Aborting process..."));
270 GuiDialog::slotClose();
271 progressBar->setValue(0);
272 statusBar->clearMessage();
277 void GuiCompare::slotButtonBox(QAbstractButton * button)
279 switch (buttonBox->standardButton(button)) {
280 case QDialogButtonBox::Ok:
283 case QDialogButtonBox::Cancel:
292 Buffer const * GuiCompare::bufferFromFileName(string const & file) const
295 if (FileName::isAbsolute(file))
297 else if (lyxview().documentBufferView())
298 fname = support::makeAbsPath(file, fromqstr(bufferFilePath()));
301 || (!fname.exists() && !theBufferList().getBuffer(fname))) {
302 LYXERR0( "Unable to read: " << file);
305 return loadIfNeeded(fname);
309 int GuiCompare::run(bool blocking_mode)
311 progressBar->setValue(0);
313 new_buffer_ = bufferFromFileName(fromqstr(newFileCB->currentText()));
314 old_buffer_ = bufferFromFileName(fromqstr(oldFileCB->currentText()));
316 // new buffer that will carry the output
317 FileName initpath(lyxrc.document_path);
318 dest_buffer_ = newUnnamedFile(initpath, to_utf8(_("differences")));
320 if (!new_buffer_ || !old_buffer_ || !dest_buffer_)
323 dest_buffer_->changed(true);
325 //blocking mode is infinitive and we don't want diff autosave
326 //if user decides to kill ther running lyx instance
327 dest_buffer_->markClean();
329 dest_buffer_->markDirty();
332 // get the options from the dialog
333 CompareOptions options;
334 options.settings_from_new = newSettingsRB->isChecked();
335 options.author = authorCO->currentIndex();
337 // init the compare object and start it
339 compare_ = new Compare(new_buffer_, old_buffer_, dest_buffer_, options);
341 connect(compare_, SIGNAL(error()), this, SLOT(error()));
342 // Only connect the finished() method to the signal if we're *not* in blocking_mode
343 // (i.e. we want to make it possible for caller to block for the results)
344 if (! blocking_mode) {
345 connect(compare_, SIGNAL(finished(bool)), this, SLOT(finished(bool)));
347 connect(compare_, SIGNAL(progress(int)), this, SLOT(progress(int)));
348 connect(compare_, SIGNAL(progressMax(int)), this, SLOT(progressMax(int)));
349 connect(compare_, SIGNAL(statusMessage(QString)),
350 this, SLOT(setStatusMessage(QString)));
351 compare_->start(QThread::LowPriority);
356 bool GuiCompare::initialiseParams(std::string const &par)
358 //just for the sake of parsing arguments
359 FuncRequest cmd(LFUN_UNKNOWN_ACTION, par);
360 if (cmd.getArg(0) == "run" || cmd.getArg(0) == "run-blocking") {
361 oldFileCB->setEditText(toqstr(cmd.getArg(1)));
362 newFileCB->setEditText(toqstr(cmd.getArg(2)));
364 if (cmd.getArg(0) == "run" ) {
365 // Run asynchronously
370 enableControls(false);
377 // Wait for the Compare function to process in a thread
381 //Hiding dialog does not work as intended through finished routine, because showView
382 //is triggered after initialiseParams returns true. So we return false, warning will
383 //show on the terminal though.
388 progressBar->setValue(0);
389 progressBar->setEnabled(false);
390 progressBar->setMaximum(1);
392 // If empty fill the author combobox with the current and the comparison
393 // author and their respective colors
394 if (authorCO->count() == 0) {
396 QPixmap colorIcon(32, 32);
397 colorIcon.fill(guiApp->colorCache().get(
398 Color(Color_changedtext_workarea_author1)));
399 authorCO->addItem(colorIcon, qt_("Current Author"));
400 colorIcon.fill(guiApp->colorCache().get(
401 Color(Color_changedtext_workarea_comparison)));
402 authorCO->addItem(colorIcon, qt_("Document Comparison"));
409 } // namespace frontend
413 #include "moc_GuiCompare.cpp"