]>
cloud.milkyroute.net Git - dolphin.git/blob - src/fileviewsvnplugin.cpp
1 /***************************************************************************
2 * Copyright (C) 2009 by Peter Penz <peter.penz@gmx.at> *
4 * This program is free software; you can redistribute it and/or modify *
5 * it under the terms of the GNU General Public License as published by *
6 * the Free Software Foundation; either version 2 of the License, or *
7 * (at your option) any later version. *
9 * This program is distributed in the hope that it will be useful, *
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of *
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
12 * GNU General Public License for more details. *
14 * You should have received a copy of the GNU General Public License *
15 * along with this program; if not, write to the *
16 * Free Software Foundation, Inc., *
17 * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA *
18 ***************************************************************************/
20 #include "fileviewsvnplugin.h"
24 #include <kfileitem.h>
34 #include <QStringList>
36 #include <QTextStream>
38 FileViewSvnPlugin::FileViewSvnPlugin() :
42 m_showLocalChangesAction(0),
48 m_operationCompletedMsg(),
53 m_updateAction
= new KAction(this);
54 m_updateAction
->setIcon(KIcon("view-refresh"));
55 m_updateAction
->setText(i18nc("@item:inmenu", "SVN Update"));
56 connect(m_updateAction
, SIGNAL(triggered()),
57 this, SLOT(updateFiles()));
59 m_showLocalChangesAction
= new KAction(this);
60 m_showLocalChangesAction
->setIcon(KIcon("view-split-left-right"));
61 m_showLocalChangesAction
->setText(i18nc("@item:inmenu", "Show Local SVN Changes"));
62 connect(m_showLocalChangesAction
, SIGNAL(triggered()),
63 this, SLOT(showLocalChanges()));
65 m_commitAction
= new KAction(this);
66 m_commitAction
->setText(i18nc("@item:inmenu", "SVN Commit..."));
67 connect(m_commitAction
, SIGNAL(triggered()),
68 this, SLOT(commitFiles()));
70 m_addAction
= new KAction(this);
71 m_addAction
->setIcon(KIcon("list-add"));
72 m_addAction
->setText(i18nc("@item:inmenu", "SVN Add"));
73 connect(m_addAction
, SIGNAL(triggered()),
74 this, SLOT(addFiles()));
76 m_removeAction
= new KAction(this);
77 m_removeAction
->setIcon(KIcon("list-remove"));
78 m_removeAction
->setText(i18nc("@item:inmenu", "SVN Delete"));
79 connect(m_removeAction
, SIGNAL(triggered()),
80 this, SLOT(removeFiles()));
83 FileViewSvnPlugin::~FileViewSvnPlugin()
87 QString
FileViewSvnPlugin::fileName() const
92 bool FileViewSvnPlugin::beginRetrieval(const QString
& directory
)
94 Q_ASSERT(directory
.endsWith('/'));
96 QStringList arguments
;
97 arguments
<< "status" << "--show-updates" << directory
;
100 process
.start("svn", arguments
);
101 while (process
.waitForReadyRead()) {
103 while (process
.readLine(buffer
, sizeof(buffer
)) > 0) {
104 VersionState state
= NormalVersion
;
105 QString
filePath(buffer
);
108 case '?': state
= UnversionedVersion
; break;
109 case 'M': state
= LocallyModifiedVersion
; break;
110 case 'A': state
= AddedVersion
; break;
111 case 'D': state
= RemovedVersion
; break;
112 case 'C': state
= ConflictingVersion
; break;
114 if (filePath
.contains('*')) {
115 state
= UpdateRequiredVersion
;
120 int pos
= filePath
.indexOf('/');
121 const int length
= filePath
.length() - pos
- 1;
122 filePath
= filePath
.mid(pos
, length
);
123 if (!filePath
.isEmpty()) {
124 m_versionInfoHash
.insert(filePath
, state
);
129 m_versionInfoKeys
= m_versionInfoHash
.keys();
133 void FileViewSvnPlugin::endRetrieval()
137 KVersionControlPlugin::VersionState
FileViewSvnPlugin::versionState(const KFileItem
& item
)
139 const QString itemUrl
= item
.localPath();
140 if (m_versionInfoHash
.contains(itemUrl
)) {
141 return m_versionInfoHash
.value(itemUrl
);
145 // files that have not been listed by 'svn status' (= m_versionInfoHash)
146 // are under version control per definition
147 return NormalVersion
;
150 // The item is a directory. Check whether an item listed by 'svn status' (= m_versionInfoHash)
151 // is part of this directory. In this case a local modification should be indicated in the
152 // directory already.
153 foreach (const QString
& key
, m_versionInfoKeys
) {
154 if (key
.startsWith(itemUrl
)) {
155 const VersionState state
= m_versionInfoHash
.value(key
);
156 if (state
== LocallyModifiedVersion
) {
157 return LocallyModifiedVersion
;
162 return NormalVersion
;
165 QList
<QAction
*> FileViewSvnPlugin::contextMenuActions(const KFileItemList
& items
)
167 Q_ASSERT(!items
.isEmpty());
168 foreach (const KFileItem
& item
, items
) {
169 m_contextItems
.append(item
);
171 m_contextDir
.clear();
173 // iterate all items and check the version state to know which
174 // actions can be enabled
175 const int itemsCount
= items
.count();
176 int versionedCount
= 0;
177 int editingCount
= 0;
178 foreach (const KFileItem
& item
, items
) {
179 const VersionState state
= versionState(item
);
180 if (state
!= UnversionedVersion
) {
185 case LocallyModifiedVersion
:
186 case ConflictingVersion
:
193 m_commitAction
->setEnabled(editingCount
> 0);
194 m_addAction
->setEnabled(versionedCount
== 0);
195 m_removeAction
->setEnabled(versionedCount
== itemsCount
);
197 QList
<QAction
*> actions
;
198 actions
.append(m_updateAction
);
199 actions
.append(m_commitAction
);
200 actions
.append(m_addAction
);
201 actions
.append(m_removeAction
);
205 QList
<QAction
*> FileViewSvnPlugin::contextMenuActions(const QString
& directory
)
207 const bool enabled
= m_contextItems
.isEmpty();
209 m_contextDir
= directory
;
212 // Only enable the SVN actions if no SVN commands are
213 // executed currently (see slotOperationCompleted() and
214 // startSvnCommandProcess()).
215 m_updateAction
->setEnabled(enabled
);
216 m_showLocalChangesAction
->setEnabled(enabled
);
217 m_commitAction
->setEnabled(enabled
);
219 QList
<QAction
*> actions
;
220 actions
.append(m_updateAction
);
221 actions
.append(m_showLocalChangesAction
);
222 actions
.append(m_commitAction
);
226 void FileViewSvnPlugin::updateFiles()
228 execSvnCommand("update",
229 i18nc("@info:status", "Updating SVN repository..."),
230 i18nc("@info:status", "Update of SVN repository failed."),
231 i18nc("@info:status", "Updated SVN repository."));
234 void FileViewSvnPlugin::showLocalChanges()
236 Q_ASSERT(!m_contextDir
.isEmpty());
237 Q_ASSERT(m_contextItems
.isEmpty());
239 const QString command
= "mkfifo /tmp/fifo; svn diff " +
240 KShell::quoteArg(m_contextDir
) +
241 " > /tmp/fifo & kompare /tmp/fifo; rm /tmp/fifo";
242 KRun::runCommand(command
, 0);
245 void FileViewSvnPlugin::commitFiles()
247 KDialog
dialog(0, Qt::Dialog
);
249 KVBox
* box
= new KVBox(&dialog
);
250 new QLabel(i18nc("@label", "Description:"), box
);
251 QTextEdit
* editor
= new QTextEdit(box
);
253 dialog
.setMainWidget(box
);
254 dialog
.setCaption(i18nc("@title:window", "SVN Commit"));
255 dialog
.setButtons(KDialog::Ok
| KDialog::Cancel
);
256 dialog
.setDefaultButton(KDialog::Ok
);
257 dialog
.setButtonText(KDialog::Ok
, i18nc("@action:button", "Commit"));
259 KConfigGroup
dialogConfig(KSharedConfig::openConfig("dolphinrc"),
261 dialog
.restoreDialogSize(dialogConfig
);
263 if (dialog
.exec() == QDialog::Accepted
) {
264 // Write the commit description into a temporary file, so
265 // that it can be read by the command "svn commit -F". The temporary
266 // file must stay alive until slotOperationCompleted() is invoked and will
267 // be destroyed when the version plugin is destructed.
268 if (!m_tempFile
.open()) {
269 emit
errorMessage(i18nc("@info:status", "Commit of SVN changes failed."));
273 QTextStream
out(&m_tempFile
);
274 const QString fileName
= m_tempFile
.fileName();
275 out
<< editor
->toPlainText();
278 execSvnCommand("commit -F " + KShell::quoteArg(fileName
),
279 i18nc("@info:status", "Committing SVN changes..."),
280 i18nc("@info:status", "Commit of SVN changes failed."),
281 i18nc("@info:status", "Committed SVN changes."));
284 dialog
.saveDialogSize(dialogConfig
, KConfigBase::Persistent
);
287 void FileViewSvnPlugin::addFiles()
289 execSvnCommand("add",
290 i18nc("@info:status", "Adding files to SVN repository..."),
291 i18nc("@info:status", "Adding of files to SVN repository failed."),
292 i18nc("@info:status", "Added files to SVN repository."));
295 void FileViewSvnPlugin::removeFiles()
297 execSvnCommand("remove",
298 i18nc("@info:status", "Removing files from SVN repository..."),
299 i18nc("@info:status", "Removing of files from SVN repository failed."),
300 i18nc("@info:status", "Removed files from SVN repository."));
303 void FileViewSvnPlugin::slotOperationCompleted()
305 if (m_contextItems
.isEmpty()) {
306 emit
operationCompletedMessage(m_operationCompletedMsg
);
307 emit
versionStatesChanged();
309 startSvnCommandProcess();
313 void FileViewSvnPlugin::slotOperationError()
315 emit
errorMessage(m_errorMsg
);
317 // don't do any operation on other items anymore
318 m_contextItems
.clear();
321 void FileViewSvnPlugin::execSvnCommand(const QString
& svnCommand
,
322 const QString
& infoMsg
,
323 const QString
& errorMsg
,
324 const QString
& operationCompletedMsg
)
326 emit
infoMessage(infoMsg
);
328 m_command
= svnCommand
;
329 m_errorMsg
= errorMsg
;
330 m_operationCompletedMsg
= operationCompletedMsg
;
332 startSvnCommandProcess();
335 void FileViewSvnPlugin::startSvnCommandProcess()
337 QProcess
* process
= new QProcess(this);
338 connect(process
, SIGNAL(finished(int)),
339 this, SLOT(slotOperationCompleted()));
340 connect(process
, SIGNAL(error(QProcess::ProcessError
)),
341 this, SLOT(slotOperationError()));
343 const QString program
= "svn " + m_command
+ ' ';
344 if (!m_contextDir
.isEmpty()) {
345 process
->start(program
+ KShell::quoteArg(m_contextDir
));
346 m_contextDir
.clear();
348 const KFileItem item
= m_contextItems
.takeLast();
349 process
->start(program
+ KShell::quoteArg(item
.localPath()));
350 // the remaining items of m_contextItems will be executed
351 // after the process has finished (see slotOperationFinished())