setXMLFile("dolphinpart.rc");
connect(m_view, SIGNAL(infoMessage(QString)),
- this, SLOT(slotInfoMessage(QString)));
+ this, SLOT(slotMessage(QString)));
+ connect(m_view, SIGNAL(operationCompletedMessage(QString)),
+ this, SLOT(slotMessage(QString)));
connect(m_view, SIGNAL(errorMessage(QString)),
this, SLOT(slotErrorMessage(QString)));
connect(m_view, SIGNAL(itemTriggered(KFileItem)),
slotCompleted(url);
}
-void DolphinPart::slotInfoMessage(const QString& msg)
+void DolphinPart::slotMessage(const QString& msg)
{
emit setStatusBarText(msg);
}
private Q_SLOTS:
void slotCompleted(const KUrl& url);
void slotCanceled(const KUrl& url);
- void slotInfoMessage(const QString& msg);
+ void slotMessage(const QString& msg);
void slotErrorMessage(const QString& msg);
/**
* Shows the information for the item \a item inside the statusbar. If the
void DolphinStatusBar::setMessage(const QString& msg,
Type type)
{
+ if (msg.isEmpty()) {
+ // show the default text as fallback
+ clear();
+ return;
+ }
+
if ((msg == m_messageLabel->text()) && (type == m_messageLabel->type())) {
+ // the message is already shown
return;
}
m_previewGenerator->setPreviewShown(m_showPreview);
m_revisionControlObserver = new RevisionControlObserver(view);
+ connect(m_revisionControlObserver, SIGNAL(infoMessage(const QString&)),
+ this, SIGNAL(infoMessage(const QString&)));
+ connect(m_revisionControlObserver, SIGNAL(errorMessage(const QString&)),
+ this, SIGNAL(errorMessage(const QString&)));
+ connect(m_revisionControlObserver, SIGNAL(operationCompletedMessage(const QString&)),
+ this, SIGNAL(operationCompletedMessage(const QString&)));
if (DolphinSettings::instance().generalSettings()->showToolTips()) {
m_toolTipManager = new ToolTipManager(view, m_proxyModel);
void DolphinViewContainer::showItemInfo(const KFileItem& item)
{
if (item.isNull()) {
- m_statusBar->clear();
+ // Only clear the status bar if unimportant messages are shown.
+ // This prevents that information- or error-messages get hidden
+ // by moving the mouse above the viewport or when closing the
+ // context menu.
+ if (m_statusBar->type() == DolphinStatusBar::Default) {
+ m_statusBar->clear();
+ }
} else {
m_statusBar->setMessage(item.getStatusBarInfo(), DolphinStatusBar::Default);
}
#include "revisioncontrolplugin.h"
#include <kdirlister.h>
+#include <klocale.h>
#include <QAbstractProxyModel>
#include <QAbstractItemView>
void setData(RevisionControlPlugin* plugin,
const QList<RevisionControlObserver::ItemState>& itemStates);
QList<RevisionControlObserver::ItemState> itemStates() const;
-
+ bool retrievedItems() const;
+
protected:
virtual void run();
private:
+ bool m_retrievedItems;
RevisionControlPlugin* m_plugin;
QMutex* m_pluginMutex;
QList<RevisionControlObserver::ItemState> m_itemStates;
UpdateItemStatesThread::UpdateItemStatesThread(QObject* parent, QMutex* pluginMutex) :
QThread(parent),
- m_pluginMutex(pluginMutex)
+ m_retrievedItems(false),
+ m_pluginMutex(pluginMutex),
+ m_itemStates()
{
}
const QString directory = m_itemStates.first().item.url().directory(KUrl::AppendTrailingSlash);
QMutexLocker locker(m_pluginMutex);
+ m_retrievedItems = false;
if (m_plugin->beginRetrieval(directory)) {
const int count = m_itemStates.count();
for (int i = 0; i < count; ++i) {
m_itemStates[i].revision = m_plugin->revisionState(m_itemStates[i].item);
}
m_plugin->endRetrieval();
+ m_retrievedItems = true;
}
}
return m_itemStates;
}
+bool UpdateItemStatesThread::retrievedItems() const
+{
+ return m_retrievedItems;
+}
+
// ------------------------------------------------------------------------------------------------
RevisionControlObserver::RevisionControlObserver(QAbstractItemView* view) :
if (m_plugin == 0) {
// TODO: just for testing purposes. A plugin approach will be used later.
m_plugin = new SubversionPlugin();
+ connect(m_plugin, SIGNAL(infoMessage(const QString&)),
+ this, SIGNAL(infoMessage(const QString&)));
+ connect(m_plugin, SIGNAL(errorMessage(const QString&)),
+ this, SIGNAL(errorMessage(const QString&)));
+ connect(m_plugin, SIGNAL(operationCompletedMessage(const QString&)),
+ this, SIGNAL(operationCompletedMessage(const QString&)));
}
revisionControlUrl.addPath(m_plugin->fileName());
void RevisionControlObserver::applyUpdatedItemStates()
{
+ if (!m_updateItemStatesThread->retrievedItems()) {
+ emit errorMessage(i18nc("@info:status", "Update of revision information failed."));
+ return;
+ }
+
// QAbstractItemModel::setData() triggers a bottleneck in combination with QListView
// (a detailed description of the root cause is given in the class KFilePreviewGenerator
// from kdelibs). To bypass this bottleneck, the signals of the model are temporary blocked.
m_dolphinModel->blockSignals(signalsBlocked);
m_view->viewport()->repaint();
+
+ // Using an empty message results in clearing the previously shown information message and showing
+ // the default status bar information. This is useful as the user already gets feedback that the
+ // operation has been completed because of the icon emblems.
+ emit operationCompletedMessage(QString());
if (m_pendingItemStatesUpdate) {
m_pendingItemStatesUpdate = false;
itemStates.append(itemState);
}
+ emit infoMessage(i18nc("@info:status", "Updating revision information..."));
m_updateItemStatesThread->setData(m_plugin, itemStates);
m_updateItemStatesThread->start(); // applyUpdatedItemStates() is called when finished
}
QList<QAction*> contextMenuActions(const KFileItemList& items) const;
QList<QAction*> contextMenuActions(const QString& directory) const;
+
+signals:
+ /**
+ * Is emitted if an information message with the content \a msg
+ * should be shown.
+ */
+ void infoMessage(const QString& msg);
+
+ /**
+ * Is emitted if an error message with the content \a msg
+ * should be shown.
+ */
+ void errorMessage(const QString& msg);
+ /**
+ * Is emitted if an "operation completed" message with the content \a msg
+ * should be shown.
+ */
+ void operationCompletedMessage(const QString& msg);
+
private slots:
void delayedDirectoryVerification();
void verifyDirectory();
m_commitAction(0),
m_addAction(0),
m_removeAction(0),
+ m_command(),
+ m_errorMsg(),
+ m_operationCompletedMsg(),
m_contextDir(),
m_contextItems()
{
QList<QAction*> SubversionPlugin::contextMenuActions(const KFileItemList& items)
{
Q_ASSERT(!items.isEmpty());
-
- m_contextItems = items;
+ foreach (const KFileItem& item, items) {
+ m_contextItems.append(item);
+ }
m_contextDir.clear();
// iterate all items and check the revision state to know which
QList<QAction*> SubversionPlugin::contextMenuActions(const QString& directory)
{
- m_contextDir = directory;
- m_contextItems.clear();
+ const bool enabled = m_contextItems.isEmpty();
+ if (enabled) {
+ m_contextDir = directory;
+ }
+
+ // Only enable the SVN actions if no SVN commands are
+ // executed currently (see slotOperationCompleted() and
+ // startSvnCommandProcess()).
+ m_updateAction->setEnabled(enabled);
+ m_showLocalChangesAction->setEnabled(enabled);
+ m_commitAction->setEnabled(enabled);
QList<QAction*> actions;
actions.append(m_updateAction);
void SubversionPlugin::updateFiles()
{
- execSvnCommand("update");
+ execSvnCommand("update",
+ i18nc("@info:status", "Updating SVN repository..."),
+ i18nc("@info:status", "Update of SVN repository failed."),
+ i18nc("@info:status", "Updated SVN repository."));
}
void SubversionPlugin::showLocalChanges()
if (dialog.exec() == QDialog::Accepted) {
const QString description = editor->toPlainText();
- execSvnCommand("commit -m " + KShell::quoteArg(description));
+ execSvnCommand("commit -m " + KShell::quoteArg(description),
+ i18nc("@info:status", "Committing SVN changes..."),
+ i18nc("@info:status", "Commit of SVN changes failed."),
+ i18nc("@info:status", "Committed SVN changes."));
}
dialog.saveDialogSize(dialogConfig, KConfigBase::Persistent);
void SubversionPlugin::addFiles()
{
- execSvnCommand("add");
+ execSvnCommand("add",
+ i18nc("@info:status", "Adding files to SVN repository..."),
+ i18nc("@info:status", "Adding of files to SVN repository failed."),
+ i18nc("@info:status", "Added files to SVN repository."));
}
void SubversionPlugin::removeFiles()
{
- execSvnCommand("remove");
+ execSvnCommand("remove",
+ i18nc("@info:status", "Removing files from SVN repository..."),
+ i18nc("@info:status", "Removing of files from SVN repository failed."),
+ i18nc("@info:status", "Removed files from SVN repository."));
+}
+
+void SubversionPlugin::slotOperationCompleted()
+{
+ if (m_contextItems.isEmpty()) {
+ emit operationCompletedMessage(m_operationCompletedMsg);
+ } else {
+ startSvnCommandProcess();
+ }
+}
+
+void SubversionPlugin::slotOperationError()
+{
+ emit errorMessage(m_errorMsg);
+
+ // don't do any operation on other items anymore
+ m_contextItems.clear();
+}
+
+void SubversionPlugin::execSvnCommand(const QString& svnCommand,
+ const QString& infoMsg,
+ const QString& errorMsg,
+ const QString& operationCompletedMsg)
+{
+ emit infoMessage(infoMsg);
+
+ m_command = svnCommand;
+ m_errorMsg = errorMsg;
+ m_operationCompletedMsg = operationCompletedMsg;
+
+ startSvnCommandProcess();
}
-void SubversionPlugin::execSvnCommand(const QString& svnCommand)
+void SubversionPlugin::startSvnCommandProcess()
{
- const QString command = "svn " + svnCommand + ' ';
+ QProcess* process = new QProcess(this);
+ connect(process, SIGNAL(finished(int)),
+ this, SLOT(slotOperationCompleted()));
+ connect(process, SIGNAL(error(QProcess::ProcessError)),
+ this, SLOT(slotOperationError()));
+
+ QStringList arguments;
+ arguments << m_command;
if (!m_contextDir.isEmpty()) {
- KRun::runCommand(command + KShell::quoteArg(m_contextDir), 0);
+ process->start("svn", arguments << KShell::quoteArg(m_contextDir));
+ m_contextDir.clear();
} else {
- foreach (const KFileItem& item, m_contextItems) {
- KRun::runCommand(command + KShell::quoteArg(item.localPath()), 0);
- }
+ const KFileItem item = m_contextItems.takeLast();
+ process->start("svn", arguments << KShell::quoteArg(item.localPath()));
+ // the remaining items of m_contextItems will be executed
+ // after the process has finished (see slotOperationFinished())
}
}
* RevisionControlPlugin::endRetrieval().
*/
void revisionStatesChanged(const QString& directory);
+
+ /**
+ * Is emitted if an information message with the content \a msg
+ * should be shown.
+ */
+ void infoMessage(const QString& msg);
+
+ /**
+ * Is emitted if an error message with the content \a msg
+ * should be shown.
+ */
+ void errorMessage(const QString& msg);
+
+ /**
+ * Is emitted if an "operation completed" message with the content \a msg
+ * should be shown.
+ */
+ void operationCompletedMessage(const QString& msg);
};
void addFiles();
void removeFiles();
+ void slotOperationCompleted();
+ void slotOperationError();
+
private:
/**
* Executes the command "svn {svnCommand}" for the files that have been
* set by getting the context menu actions (see contextMenuActions()).
+ * @param infoMsg Message that should be shown before the command is executed.
+ * @param errorMsg Message that should be shown if the execution of the command
+ * has been failed.
+ * @param operationCompletedMsg
+ * Message that should be shown if the execution of the command
+ * has been completed successfully.
*/
- void execSvnCommand(const QString& svnCommand);
+ void execSvnCommand(const QString& svnCommand,
+ const QString& infoMsg,
+ const QString& errorMsg,
+ const QString& operationCompletedMsg);
+
+ void startSvnCommandProcess();
private:
QHash<QString, RevisionState> m_revisionInfoHash;
QAction* m_commitAction;
QAction* m_addAction;
QAction* m_removeAction;
- mutable QString m_contextDir;
- mutable KFileItemList m_contextItems;
+
+ QString m_command;
+ QString m_errorMsg;
+ QString m_operationCompletedMsg;
+
+ QString m_contextDir;
+ KFileItemList m_contextItems;
};
#endif // REVISIONCONTROLPLUGIN_H