• Skip to content
  • Skip to link menu
KDE API Reference
  • KDE API Reference
  • kdesdk API Reference
  • KDE Home
  • Contact Us
 

lokalize

  • sources
  • kde-4.14
  • kdesdk
  • lokalize
  • src
  • mergemode
mergeview.cpp
Go to the documentation of this file.
1 /* ****************************************************************************
2  This file is part of Lokalize
3 
4  Copyright (C) 2007-2012 by Nick Shaforostoff <shafff@ukr.net>
5 
6  This program is free software; you can redistribute it and/or
7  modify it under the terms of the GNU General Public License as
8  published by the Free Software Foundation; either version 2 of
9  the License or (at your option) version 3 or any later version
10  accepted by the membership of KDE e.V. (or its successor approved
11  by the membership of KDE e.V.), which shall act as a proxy
12  defined in Section 14 of version 3 of the license.
13 
14  This program is distributed in the hope that it will be useful,
15  but WITHOUT ANY WARRANTY; without even the implied warranty of
16  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17  GNU General Public License for more details.
18 
19  You should have received a copy of the GNU General Public License
20  along with this program. If not, see <http://www.gnu.org/licenses/>.
21 
22 **************************************************************************** */
23 
24 #include "mergeview.h"
25 
26 #include "cmd.h"
27 #include "mergecatalog.h"
28 #include "project.h"
29 #include "diff.h"
30 #include "projectmodel.h"
31 
32 #include <klocale.h>
33 #include <kdebug.h>
34 #include <kurl.h>
35 #include <kfiledialog.h>
36 #include <kmessagebox.h>
37 #include <knotification.h>
38 #include <ktextedit.h>
39 #include <kaction.h>
40 #include <threadweaver/ThreadWeaver.h>
41 
42 #include <QDragEnterEvent>
43 #include <QFile>
44 #include <QToolTip>
45 
46 MergeView::MergeView(QWidget* parent, Catalog* catalog, bool primary)
47  : QDockWidget ( primary?i18nc("@title:window that displays difference between current file and 'merge source'","Primary Sync"):i18nc("@title:window that displays difference between current file and 'merge source'","Secondary Sync"), parent)
48  , m_browser(new KTextEdit(this))
49  , m_baseCatalog(catalog)
50  , m_mergeCatalog(0)
51  , m_normTitle(primary?
52  i18nc("@title:window that displays difference between current file and 'merge source'","Primary Sync"):
53  i18nc("@title:window that displays difference between current file and 'merge source'","Secondary Sync"))
54  , m_hasInfoTitle(m_normTitle+" [*]")
55  , m_hasInfo(false)
56  , m_primary(primary)
57 {
58  setObjectName(primary?"mergeView-primary":"mergeView-secondary");
59  setWidget(m_browser);
60  setToolTip(i18nc("@info:tooltip","Drop file to be merged into / synced with the current one here"));
61 
62  hide();
63 
64  setAcceptDrops(true);
65  m_browser->setReadOnly(true);
66  m_browser->setContextMenuPolicy(Qt::NoContextMenu);
67  setContextMenuPolicy(Qt::ActionsContextMenu);
68 }
69 
70 MergeView::~MergeView()
71 {
72  delete m_mergeCatalog;
73  emit mergeCatalogPointerChanged(NULL);
74 }
75 
76 KUrl MergeView::url()
77 {
78  if (m_mergeCatalog)
79  return m_mergeCatalog->url();
80  return KUrl();
81 }
82 
83 void MergeView::dragEnterEvent(QDragEnterEvent* event)
84 {
85  if(event->mimeData()->hasUrls() && Catalog::extIsSupported(event->mimeData()->urls().first().path()))
86  event->acceptProposedAction();
87 }
88 
89 void MergeView::dropEvent(QDropEvent *event)
90 {
91  mergeOpen(KUrl(event->mimeData()->urls().first()));
92  event->acceptProposedAction();
93 }
94 
95 void MergeView::slotUpdate(const DocPosition& pos)
96 {
97  if (pos.entry==m_pos.entry)
98  slotNewEntryDisplayed(pos);
99 }
100 
101 void MergeView::slotNewEntryDisplayed(const DocPosition& pos)
102 {
103  m_pos=pos;
104 
105  if (!m_mergeCatalog)
106  return;
107 
108  emit signalPriorChangedAvailable((pos.entry>m_mergeCatalog->firstChangedIndex())
109  ||(pluralFormsAvailableBackward()!=-1));
110  emit signalNextChangedAvailable((pos.entry<m_mergeCatalog->lastChangedIndex())
111  ||(pluralFormsAvailableForward()!=-1));
112 
113  if (!m_mergeCatalog->isPresent(pos.entry))
114  {
115  //i.e. no corresponding entry, whether changed or not
116  if (m_hasInfo)
117  {
118  m_hasInfo=false;
119  setWindowTitle(m_normTitle);
120  m_browser->clear();
121 // m_browser->viewport()->setBackgroundRole(QPalette::Base);
122  }
123  emit signalEntryWithMergeDisplayed(false);
124 
126  return;
127  }
128  if (!m_hasInfo)
129  {
130  m_hasInfo=true;
131  setWindowTitle(m_hasInfoTitle);
132  }
133 
134  emit signalEntryWithMergeDisplayed(m_mergeCatalog->isDifferent(pos.entry));
135 
136  QString result=userVisibleWordDiff(m_baseCatalog->msgstr(pos),
137  m_mergeCatalog->msgstr(pos),
138  Project::instance()->accel(),
139  Project::instance()->markup(),
140  Html);
141 #if 0
142  int i=-1;
143  bool inTag=false;
144  while(++i<result.size())//dynamic
145  {
146  if (!inTag)
147  {
148  if (result.at(i)=='<')
149  inTag=true;
150  else if (result.at(i)==' ')
151  result.replace(i,1,"&sp;");
152  }
153  else if (result.at(i)=='>')
154  inTag=false;
155  }
156 #endif
157 
158  if (!m_mergeCatalog->isApproved(pos.entry))
159  {
160  result.prepend("<i>");
161  result.append("</i>");
162  }
163 
164  if (m_mergeCatalog->isModified(pos))
165  {
166  result.prepend("<b>");
167  result.append("</b>");
168  }
169 
170  m_browser->setHtml(result);
171 // kWarning()<<"ELA "<<time.elapsed();
172 }
173 
174 void MergeView::cleanup()
175 {
176  delete m_mergeCatalog;
177  m_mergeCatalog=0;
178  emit mergeCatalogPointerChanged(m_mergeCatalog);
179  m_pos=DocPosition();
180 
181  emit signalPriorChangedAvailable(false);
182  emit signalNextChangedAvailable(false);
183 
184  m_browser->clear();
185 }
186 
187 void MergeView::mergeOpen(KUrl url)
188 {
189  if (KDE_ISUNLIKELY( !m_baseCatalog->numberOfEntries() ))
190  return;
191 
192  if (url==m_baseCatalog->url())
193  {
194  //(we are likely to be _mergeViewSecondary)
195  //special handling: open corresponding file in the branch
196  //for AutoSync
197 
198  QString path=QFileInfo(url.toLocalFile()).canonicalFilePath(); //bug 245546 regarding symlinks
199  QString oldPath=path;
200  path.replace(Project::instance()->poDir(),Project::instance()->branchDir());
201 
202  if (oldPath==path) //if file doesn't exist both are empty
203  {
204  cleanup();
205  return;
206  }
207 
208  url=KUrl(path);
209  }
210 
211  if (url.isEmpty())
212  {
213  Project::instance()->model()->weaver()->suspend();
214  url=KFileDialog::getOpenUrl(KUrl("kfiledialog:///merge-source") /*m_baseCatalog->url()*/ , Catalog::supportedMimeFilters, this);
215  Project::instance()->model()->weaver()->resume();
216  }
217  if (url.isEmpty())
218  return;
219 
220  delete m_mergeCatalog;
221  m_mergeCatalog=new MergeCatalog(this,m_baseCatalog);
222  emit mergeCatalogPointerChanged(m_mergeCatalog);
223  int errorLine=m_mergeCatalog->loadFromUrl(url);
224  if (KDE_ISLIKELY( errorLine==0 ))
225  {
226  if (m_pos.entry>0)
227  emit signalPriorChangedAvailable(m_pos.entry>m_mergeCatalog->firstChangedIndex());
228 
229  emit signalNextChangedAvailable(m_pos.entry<m_mergeCatalog->lastChangedIndex());
230 
231  //a bit hacky :)
232  connect (m_mergeCatalog,SIGNAL(signalEntryModified(DocPosition)),this,SLOT(slotUpdate(DocPosition)));
233 
234  if (m_pos.entry!=-1)
235  slotNewEntryDisplayed(m_pos);
236  show();
237  }
238  else
239  {
240  //KMessageBox::error(this, KIO::NetAccess::lastErrorString() );
241  cleanup();
242  if (errorLine>0)
243  KMessageBox::error(this, i18nc("@info","Error opening the file <filename>%1</filename> for synchronization, error line: %2",url.pathOrUrl(),errorLine) );
244  else
245  {
246  /* disable this as requested by bug 272587
247  KNotification* notification=new KNotification("MergeFilesOpenError", this);
248  notification->setText( i18nc("@info %1 is full filename","Error opening the file <filename>%1</filename> for synchronization",url.pathOrUrl()) );
249  notification->sendEvent();
250  */
251  }
252  //i18nc("@info %1 is w/o path","No branch counterpart for <filename>%1</filename>",url.fileName()),
253  }
254 
255 }
256 
257 int MergeView::pluralFormsAvailableForward()
258 {
259  if(KDE_ISLIKELY( m_pos.entry==-1 || !m_mergeCatalog->isPlural(m_pos.entry) ))
260  return -1;
261 
262  int formLimit=qMin(m_baseCatalog->numberOfPluralForms(),m_mergeCatalog->numberOfPluralForms());//just sanity check
263  DocPosition pos=m_pos;
264  while (++(pos.form)<formLimit)
265  {
266  if (m_baseCatalog->msgstr(pos)!=m_mergeCatalog->msgstr(pos))
267  return pos.form;
268  }
269  return -1;
270 }
271 
272 int MergeView::pluralFormsAvailableBackward()
273 {
274  if(KDE_ISLIKELY( m_pos.entry==-1 || !m_mergeCatalog->isPlural(m_pos.entry) ))
275  return -1;
276 
277  DocPosition pos=m_pos;
278  while (--(pos.form)>=0)
279  {
280  if (m_baseCatalog->msgstr(pos)!=m_mergeCatalog->msgstr(pos))
281  return pos.form;
282  }
283  return -1;
284 }
285 
286 void MergeView::gotoPrevChanged()
287 {
288  if (KDE_ISUNLIKELY( !m_mergeCatalog ))
289  return;
290 
291  DocPosition pos;
292 
293  //first, check if there any plural forms waiting to be synced
294  int form=pluralFormsAvailableBackward();
295  if (KDE_ISUNLIKELY( form!=-1 ))
296  {
297  pos=m_pos;
298  pos.form=form;
299  }
300  else if(KDE_ISUNLIKELY( (pos.entry=m_mergeCatalog->prevChangedIndex(m_pos.entry)) == -1 ))
301  return;
302 
303  if (KDE_ISUNLIKELY( m_mergeCatalog->isPlural(pos.entry)&&form==-1 ))
304  pos.form=qMin(m_baseCatalog->numberOfPluralForms(),m_mergeCatalog->numberOfPluralForms())-1;
305 
306  emit gotoEntry(pos,0);
307 }
308 
309 void MergeView::gotoNextChangedApproved()
310 {
311  gotoNextChanged(true);
312 }
313 
314 void MergeView::gotoNextChanged(bool approvedOnly)
315 {
316  if (KDE_ISUNLIKELY( !m_mergeCatalog ))
317  return;
318 
319  DocPosition pos=m_pos;
320 
321  //first, check if there any plural forms waiting to be synced
322  int form=pluralFormsAvailableForward();
323  if (KDE_ISUNLIKELY( form!=-1 ))
324  {
325  pos=m_pos;
326  pos.form=form;
327  }
328  else if(KDE_ISUNLIKELY( (pos.entry=m_mergeCatalog->nextChangedIndex(m_pos.entry)) == -1 ))
329  return;
330 
331  while (approvedOnly && !m_mergeCatalog->isApproved(pos.entry))
332  {
333  if(KDE_ISUNLIKELY( (pos.entry=m_mergeCatalog->nextChangedIndex(pos.entry)) == -1 ))
334  return;
335  }
336 
337  emit gotoEntry(pos,0);
338 }
339 
340 void MergeView::mergeBack()
341 {
342  if(m_pos.entry==-1 ||!m_mergeCatalog ||m_baseCatalog->msgstr(m_pos).isEmpty())
343  return;
344 
345  m_mergeCatalog->copyFromBaseCatalog(m_pos);
346 }
347 
348 void MergeView::mergeAccept()
349 {
350  if(m_pos.entry==-1
351  ||!m_mergeCatalog
352  //||m_baseCatalog->msgstr(m_pos)==m_mergeCatalog->msgstr(m_pos)
353  ||m_mergeCatalog->msgstr(m_pos).isEmpty())
354  return;
355 
356  m_mergeCatalog->copyToBaseCatalog(m_pos);
357 
358  emit gotoEntry(m_pos,0);
359 }
360 
361 void MergeView::mergeAcceptAllForEmpty()
362 {
363  if(KDE_ISUNLIKELY(!m_mergeCatalog)) return;
364 
365  bool update=m_mergeCatalog->differentEntries().contains(m_pos.entry);
366 
367  m_mergeCatalog->copyToBaseCatalog(/*MergeCatalog::EmptyOnly*/MergeCatalog::HigherOnly);
368 
369  if (update!=m_mergeCatalog->differentEntries().contains(m_pos.entry))
370  emit gotoEntry(m_pos,0);
371 }
372 
373 
374 bool MergeView::event(QEvent *event)
375 {
376  if (event->type()==QEvent::ToolTip && m_mergeCatalog)
377  {
378  QHelpEvent *helpEvent = static_cast<QHelpEvent *>(event);
379  QString text="<b>" % url().prettyUrl() % "</b>\n" % i18nc("@info:tooltip","Different entries: %1\nUnmatched entries: %2",
380  m_mergeCatalog->differentEntries().count(),m_mergeCatalog->unmatchedCount());
381  text.replace('\n',"<br />");
382  QToolTip::showText(helpEvent->globalPos(),text);
383  return true;
384  }
385  return QWidget::event(event);
386 }
387 
388 #include "mergeview.moc"
MergeView::signalPriorChangedAvailable
void signalPriorChangedAvailable(bool)
QEvent
MergeCatalog
Merge source container.
Definition: mergecatalog.h:71
project.h
Html
Definition: diff.h:45
QWidget
Catalog::url
const KUrl & url() const
Definition: catalog.h:189
QString::append
QString & append(QChar ch)
QEvent::type
Type type() const
MergeCatalog::msgstr
QString msgstr(const DocPosition &) const
Definition: mergecatalog.cpp:76
QDropEvent::mimeData
const QMimeData * mimeData() const
mergeview.h
ProjectModel::weaver
ThreadWeaver::Weaver * weaver()
Definition: projectmodel.h:167
Catalog::numberOfPluralForms
int numberOfPluralForms() const
Definition: catalog.h:150
MergeView::mergeBack
void mergeBack()
Definition: mergeview.cpp:340
QDockWidget
QString::prepend
QString & prepend(QChar ch)
userVisibleWordDiff
QString userVisibleWordDiff(const QString &str1ForMatching, const QString &str2ForMatching, const QString &accel, const QString &markup, int options)
Definition: diff.cpp:408
MergeView::gotoEntry
void gotoEntry(const DocPosition &, int)
Project::instance
static Project * instance()
Definition: project.cpp:67
MergeView::~MergeView
virtual ~MergeView()
Definition: mergeview.cpp:70
MergeCatalog::differentEntries
QLinkedList< int > differentEntries() const
Definition: mergecatalog.h:85
MergeView::dropEvent
void dropEvent(QDropEvent *)
Definition: mergeview.cpp:89
MergeCatalog::isPresent
bool isPresent(const short int &entry) const
whether 'merge source' has entry with such msgid
Definition: mergecatalog.cpp:110
MergeCatalog::HigherOnly
Definition: mergecatalog.h:101
MergeCatalog::nextChangedIndex
int nextChangedIndex(uint index) const
Definition: mergecatalog.h:82
ProjectBase::markup
QString markup() const
Get Markup.
Definition: projectbase.h:252
MergeView::url
KUrl url()
Definition: mergeview.cpp:76
cmd.h
MergeCatalog::unmatchedCount
int unmatchedCount() const
Definition: mergecatalog.h:93
MergeView::gotoNextChangedApproved
void gotoNextChangedApproved()
Definition: mergeview.cpp:309
MergeView::slotNewEntryDisplayed
void slotNewEntryDisplayed(const DocPosition &)
Definition: mergeview.cpp:101
QToolTip::showText
void showText(const QPoint &pos, const QString &text, QWidget *w)
QWidget::update
void update()
MergeView::gotoPrevChanged
void gotoPrevChanged()
Definition: mergeview.cpp:286
DocPosition::entry
int entry
Definition: pos.h:48
QLinkedList::count
int count(const T &value) const
Catalog::extIsSupported
static bool extIsSupported(const QString &path)
Definition: catalog.cpp:93
DocPosition
This struct represents a position in a catalog.
Definition: pos.h:38
MergeView::mergeOpen
void mergeOpen(KUrl url=KUrl())
Definition: mergeview.cpp:187
ProjectBase::accel
QString accel() const
Get Accel.
Definition: projectbase.h:235
MergeCatalog::isDifferent
int isDifferent(uint index) const
Definition: mergecatalog.h:84
MergeView::gotoNextChanged
void gotoNextChanged(bool approvedOnly=false)
Definition: mergeview.cpp:314
QHelpEvent::globalPos
const QPoint & globalPos() const
QDropEvent
MergeView::mergeAccept
void mergeAccept()
Definition: mergeview.cpp:348
QObject::setObjectName
void setObjectName(const QString &name)
QString::isEmpty
bool isEmpty() const
DocPosition::form
char form
Definition: pos.h:50
Project::model
ProjectModel * model()
Definition: project.cpp:265
QWidget::pos
QPoint pos() const
QString
QWidget::hide
void hide()
mergecatalog.h
diff.h
QWidget::setAcceptDrops
void setAcceptDrops(bool on)
QFileInfo
MergeCatalog::copyFromBaseCatalog
void copyFromBaseCatalog(const DocPosition &, int options)
Definition: mergecatalog.cpp:48
QWidget::setContextMenuPolicy
void setContextMenuPolicy(Qt::ContextMenuPolicy policy)
QDockWidget::setWidget
void setWidget(QWidget *widget)
QString::replace
QString & replace(int position, int n, QChar after)
MergeView::slotUpdate
void slotUpdate(const DocPosition &)
Definition: mergeview.cpp:95
projectmodel.h
QMimeData::hasUrls
bool hasUrls() const
QDragEnterEvent
QMimeData::urls
QList< QUrl > urls() const
MergeView::signalEntryWithMergeDisplayed
void signalEntryWithMergeDisplayed(bool)
MergeCatalog::isModified
bool isModified(DocPos) const
Definition: mergecatalog.cpp:250
MergeView::mergeAcceptAllForEmpty
void mergeAcceptAllForEmpty()
Definition: mergeview.cpp:361
QWidget::setWindowTitle
void setWindowTitle(const QString &)
Catalog::numberOfEntries
int numberOfEntries() const
Definition: catalog.cpp:171
MergeCatalog::isPlural
bool isPlural(uint index) const
Definition: mergecatalog.cpp:98
Catalog::supportedMimeFilters
static QString supportedMimeFilters
Definition: catalog.h:259
MergeCatalog::lastChangedIndex
int lastChangedIndex() const
Definition: mergecatalog.h:81
MergeView::MergeView
MergeView(QWidget *, Catalog *, bool primary)
Definition: mergeview.cpp:46
Catalog
This class represents a catalog It uses CatalogStorage interface to work with catalogs in different f...
Definition: catalog.h:74
QWidget::show
void show()
QWidget::setToolTip
void setToolTip(const QString &)
MergeView::signalNextChangedAvailable
void signalNextChangedAvailable(bool)
MergeCatalog::prevChangedIndex
int prevChangedIndex(uint index) const
Definition: mergecatalog.h:83
QObject::connect
bool connect(const QObject *sender, const char *signal, const QObject *receiver, const char *method, Qt::ConnectionType type)
QHelpEvent
Catalog::msgstr
virtual QString msgstr(const DocPosition &) const
Definition: catalog.cpp:195
MergeCatalog::isApproved
bool isApproved(uint index) const
Definition: mergecatalog.cpp:84
QWidget::event
virtual bool event(QEvent *event)
MergeView::mergeCatalogPointerChanged
void mergeCatalogPointerChanged(MergeCatalog *mergeCatalog)
MergeCatalog::firstChangedIndex
int firstChangedIndex() const
Definition: mergecatalog.h:80
MergeView::cleanup
void cleanup()
Definition: mergeview.cpp:174
QLinkedList::contains
bool contains(const T &value) const
KTextEdit
MergeCatalog::loadFromUrl
int loadFromUrl(const KUrl &url)
Definition: mergecatalog.cpp:163
MergeView::dragEnterEvent
void dragEnterEvent(QDragEnterEvent *event)
Definition: mergeview.cpp:83
MergeCatalog::copyToBaseCatalog
void copyToBaseCatalog(DocPosition &pos)
Definition: mergecatalog.cpp:263
This file is part of the KDE documentation.
Documentation copyright © 1996-2020 The KDE developers.
Generated on Mon Jun 22 2020 13:40:07 by doxygen 1.8.7 written by Dimitri van Heesch, © 1997-2006

KDE's Doxygen guidelines are available online.

lokalize

Skip menu "lokalize"
  • Main Page
  • Namespace List
  • Namespace Members
  • Alphabetical List
  • Class List
  • Class Hierarchy
  • Class Members
  • File List
  • File Members

kdesdk API Reference

Skip menu "kdesdk API Reference"
  • kapptemplate
  • kcachegrind
  • kompare
  • lokalize
  • umbrello
  •   umbrello

Search



Report problems with this website to our bug tracking system.
Contact the specific authors with questions and comments about the page contents.

KDE® and the K Desktop Environment® logo are registered trademarks of KDE e.V. | Legal