forked from qt-creator/qt-creator
Editor: Added Dialog for read only files.
Task-number: QTCREATORBUG-2851 Change-Id: Ic47a5a1833650e31b4e27d0a01259d6b398a6415 Reviewed-by: Orgad Shaneh <orgads@gmail.com> Reviewed-by: Christian Stenger <christian.stenger@digia.com> Reviewed-by: Eike Ziller <eike.ziller@digia.com>
This commit is contained in:
@@ -218,6 +218,12 @@ QString FileUtils::shortNativePath(const FileName &path)
|
|||||||
return path.toUserOutput();
|
return path.toUserOutput();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool FileUtils::makeWritable(const FileName &path)
|
||||||
|
{
|
||||||
|
const QString fileName = path.toString();
|
||||||
|
return QFile::setPermissions(fileName, QFile::permissions(fileName) | QFile::WriteUser);
|
||||||
|
}
|
||||||
|
|
||||||
QByteArray FileReader::fetchQrc(const QString &fileName)
|
QByteArray FileReader::fetchQrc(const QString &fileName)
|
||||||
{
|
{
|
||||||
QTC_ASSERT(fileName.startsWith(QLatin1Char(':')), return QByteArray());
|
QTC_ASSERT(fileName.startsWith(QLatin1Char(':')), return QByteArray());
|
||||||
|
@@ -96,6 +96,7 @@ public:
|
|||||||
static bool isFileNewerThan(const FileName &filePath, const QDateTime &timeStamp);
|
static bool isFileNewerThan(const FileName &filePath, const QDateTime &timeStamp);
|
||||||
static FileName resolveSymlinks(const FileName &path);
|
static FileName resolveSymlinks(const FileName &path);
|
||||||
static QString shortNativePath(const FileName &path);
|
static QString shortNativePath(const FileName &path);
|
||||||
|
static bool makeWritable(const FileName &path);
|
||||||
};
|
};
|
||||||
|
|
||||||
class QTCREATOR_UTILS_EXPORT FileReader
|
class QTCREATOR_UTILS_EXPORT FileReader
|
||||||
|
@@ -49,6 +49,7 @@ SOURCES += mainwindow.cpp \
|
|||||||
dialogs/settingsdialog.cpp \
|
dialogs/settingsdialog.cpp \
|
||||||
actionmanager/commandmappings.cpp \
|
actionmanager/commandmappings.cpp \
|
||||||
dialogs/shortcutsettings.cpp \
|
dialogs/shortcutsettings.cpp \
|
||||||
|
dialogs/readonlyfilesdialog.cpp \
|
||||||
dialogs/openwithdialog.cpp \
|
dialogs/openwithdialog.cpp \
|
||||||
progressmanager/progressmanager.cpp \
|
progressmanager/progressmanager.cpp \
|
||||||
progressmanager/progressview.cpp \
|
progressmanager/progressview.cpp \
|
||||||
@@ -134,6 +135,7 @@ HEADERS += mainwindow.h \
|
|||||||
dialogs/newdialog.h \
|
dialogs/newdialog.h \
|
||||||
dialogs/settingsdialog.h \
|
dialogs/settingsdialog.h \
|
||||||
actionmanager/commandmappings.h \
|
actionmanager/commandmappings.h \
|
||||||
|
dialogs/readonlyfilesdialog.h \
|
||||||
dialogs/shortcutsettings.h \
|
dialogs/shortcutsettings.h \
|
||||||
dialogs/openwithdialog.h \
|
dialogs/openwithdialog.h \
|
||||||
dialogs/iwizard.h \
|
dialogs/iwizard.h \
|
||||||
@@ -202,6 +204,7 @@ HEADERS += mainwindow.h \
|
|||||||
FORMS += dialogs/newdialog.ui \
|
FORMS += dialogs/newdialog.ui \
|
||||||
actionmanager/commandmappings.ui \
|
actionmanager/commandmappings.ui \
|
||||||
dialogs/saveitemsdialog.ui \
|
dialogs/saveitemsdialog.ui \
|
||||||
|
dialogs/readonlyfilesdialog.ui \
|
||||||
dialogs/openwithdialog.ui \
|
dialogs/openwithdialog.ui \
|
||||||
generalsettings.ui \
|
generalsettings.ui \
|
||||||
dialogs/externaltoolconfig.ui \
|
dialogs/externaltoolconfig.ui \
|
||||||
|
@@ -187,6 +187,9 @@ QtcPlugin {
|
|||||||
"dialogs/openwithdialog.ui",
|
"dialogs/openwithdialog.ui",
|
||||||
"dialogs/promptoverwritedialog.cpp",
|
"dialogs/promptoverwritedialog.cpp",
|
||||||
"dialogs/promptoverwritedialog.h",
|
"dialogs/promptoverwritedialog.h",
|
||||||
|
"dialogs/readonlyfilesdialog.cpp",
|
||||||
|
"dialogs/readonlyfilesdialog.h",
|
||||||
|
"dialogs/readonlyfilesdialog.ui",
|
||||||
"dialogs/saveitemsdialog.cpp",
|
"dialogs/saveitemsdialog.cpp",
|
||||||
"dialogs/saveitemsdialog.h",
|
"dialogs/saveitemsdialog.h",
|
||||||
"dialogs/saveitemsdialog.ui",
|
"dialogs/saveitemsdialog.ui",
|
||||||
|
491
src/plugins/coreplugin/dialogs/readonlyfilesdialog.cpp
Normal file
491
src/plugins/coreplugin/dialogs/readonlyfilesdialog.cpp
Normal file
@@ -0,0 +1,491 @@
|
|||||||
|
/****************************************************************************
|
||||||
|
**
|
||||||
|
** Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies).
|
||||||
|
** Contact: http://www.qt-project.org/legal
|
||||||
|
**
|
||||||
|
** This file is part of Qt Creator.
|
||||||
|
**
|
||||||
|
** Commercial License Usage
|
||||||
|
** Licensees holding valid commercial Qt licenses may use this file in
|
||||||
|
** accordance with the commercial license agreement provided with the
|
||||||
|
** Software or, alternatively, in accordance with the terms contained in
|
||||||
|
** a written agreement between you and Digia. For licensing terms and
|
||||||
|
** conditions see http://qt.digia.com/licensing. For further information
|
||||||
|
** use the contact form at http://qt.digia.com/contact-us.
|
||||||
|
**
|
||||||
|
** GNU Lesser General Public License Usage
|
||||||
|
** Alternatively, this file may be used under the terms of the GNU Lesser
|
||||||
|
** General Public License version 2.1 as published by the Free Software
|
||||||
|
** Foundation and appearing in the file LICENSE.LGPL included in the
|
||||||
|
** packaging of this file. Please review the following information to
|
||||||
|
** ensure the GNU Lesser General Public License version 2.1 requirements
|
||||||
|
** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
|
||||||
|
**
|
||||||
|
** In addition, as a special exception, Digia gives you certain additional
|
||||||
|
** rights. These rights are described in the Digia Qt LGPL Exception
|
||||||
|
** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
|
||||||
|
**
|
||||||
|
****************************************************************************/
|
||||||
|
|
||||||
|
#include "fileiconprovider.h"
|
||||||
|
#include "readonlyfilesdialog.h"
|
||||||
|
#include "ui_readonlyfilesdialog.h"
|
||||||
|
|
||||||
|
#include <coreplugin/editormanager/editormanager.h>
|
||||||
|
#include <coreplugin/icore.h>
|
||||||
|
#include <coreplugin/idocument.h>
|
||||||
|
#include <coreplugin/iversioncontrol.h>
|
||||||
|
#include <coreplugin/vcsmanager.h>
|
||||||
|
|
||||||
|
#include <utils/fileutils.h>
|
||||||
|
#include <utils/hostosinfo.h>
|
||||||
|
|
||||||
|
#include <QDir>
|
||||||
|
#include <QFileInfo>
|
||||||
|
#include <QMap>
|
||||||
|
#include <QMessageBox>
|
||||||
|
#include <QPushButton>
|
||||||
|
#include <QRadioButton>
|
||||||
|
|
||||||
|
namespace Core {
|
||||||
|
namespace Internal {
|
||||||
|
|
||||||
|
class ReadOnlyFilesDialogPrivate
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
ReadOnlyFilesDialogPrivate(IDocument *document = 0, bool useSaveAs = false);
|
||||||
|
~ReadOnlyFilesDialogPrivate();
|
||||||
|
|
||||||
|
// Buttongroups containing the operation for one file.
|
||||||
|
struct ButtonGroupForFile
|
||||||
|
{
|
||||||
|
QString fileName;
|
||||||
|
QButtonGroup *group;
|
||||||
|
};
|
||||||
|
QList <ButtonGroupForFile> buttonGroups;
|
||||||
|
|
||||||
|
QMap <int, int> setAllIndexForOperation;
|
||||||
|
// The version control systems for every file, if the file isn't in VCS the value is 0.
|
||||||
|
QHash <QString, IVersionControl*> versionControls;
|
||||||
|
|
||||||
|
// Define if some specific operations should be allowed to make the files writable.
|
||||||
|
const bool useSaveAs;
|
||||||
|
bool useVCS;
|
||||||
|
|
||||||
|
// Define if an error should be displayed when an operation fails.
|
||||||
|
bool showWarnings;
|
||||||
|
QString failWarning;
|
||||||
|
|
||||||
|
// The document is necessary for the Save As operation.
|
||||||
|
IDocument *document;
|
||||||
|
|
||||||
|
// Operation text for the tree widget header and combo box entries for
|
||||||
|
// modifying operations for all files.
|
||||||
|
const QString mixedText;
|
||||||
|
QString makeWritableText;
|
||||||
|
QString versionControlOpenText;
|
||||||
|
const QString saveAsText;
|
||||||
|
};
|
||||||
|
|
||||||
|
ReadOnlyFilesDialogPrivate::ReadOnlyFilesDialogPrivate(IDocument *document, bool displaySaveAs)
|
||||||
|
: useSaveAs(displaySaveAs)
|
||||||
|
, useVCS(false)
|
||||||
|
, showWarnings(false)
|
||||||
|
, document(document)
|
||||||
|
, mixedText(QApplication::translate("ReadOnlyFilesDialog", "Mixed"))
|
||||||
|
, makeWritableText(QApplication::translate("ReadOnlyFilesDialog", "Make Writable"))
|
||||||
|
, versionControlOpenText(QApplication::translate("ReadOnlyFilesDialog", "Open With VCS"))
|
||||||
|
, saveAsText(QApplication::translate("ReadOnlyFilesDialog", "Save As"))
|
||||||
|
{}
|
||||||
|
|
||||||
|
ReadOnlyFilesDialogPrivate::~ReadOnlyFilesDialogPrivate()
|
||||||
|
{
|
||||||
|
foreach (const ButtonGroupForFile &groupForFile, buttonGroups)
|
||||||
|
delete groupForFile.group;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*!
|
||||||
|
* \class ReadOnlyFilesDialog
|
||||||
|
* \brief Dialog to show a set of files which are classified as not writable.
|
||||||
|
*
|
||||||
|
* Automatically checks which operations are allowed to make the file writable. These operations
|
||||||
|
* are Make Writable which tries to set the file permissions in the file system,
|
||||||
|
* Open With Version Control System if the open operation is allowed by the version control system
|
||||||
|
* and Save As which is used to save the changes to a document in another file.
|
||||||
|
*/
|
||||||
|
|
||||||
|
ReadOnlyFilesDialog::ReadOnlyFilesDialog(const QList<QString> &fileNames, QWidget *parent)
|
||||||
|
: QDialog(parent)
|
||||||
|
, d(new ReadOnlyFilesDialogPrivate)
|
||||||
|
, ui(new Ui::ReadOnlyFilesDialog)
|
||||||
|
{
|
||||||
|
initDialog(fileNames);
|
||||||
|
}
|
||||||
|
|
||||||
|
ReadOnlyFilesDialog::ReadOnlyFilesDialog(const QString &fileName, QWidget *parent)
|
||||||
|
: QDialog(parent)
|
||||||
|
, d(new ReadOnlyFilesDialogPrivate)
|
||||||
|
, ui(new Ui::ReadOnlyFilesDialog)
|
||||||
|
{
|
||||||
|
initDialog(QStringList() << fileName);
|
||||||
|
}
|
||||||
|
|
||||||
|
ReadOnlyFilesDialog::ReadOnlyFilesDialog(IDocument *document, QWidget *parent,
|
||||||
|
bool displaySaveAs)
|
||||||
|
: QDialog(parent)
|
||||||
|
, d(new ReadOnlyFilesDialogPrivate(document, displaySaveAs))
|
||||||
|
, ui(new Ui::ReadOnlyFilesDialog)
|
||||||
|
{
|
||||||
|
initDialog(QStringList() << document->fileName());
|
||||||
|
}
|
||||||
|
|
||||||
|
ReadOnlyFilesDialog::ReadOnlyFilesDialog(const QList<IDocument *> documents, QWidget *parent)
|
||||||
|
: QDialog(parent)
|
||||||
|
, d(new ReadOnlyFilesDialogPrivate)
|
||||||
|
, ui(new Ui::ReadOnlyFilesDialog)
|
||||||
|
{
|
||||||
|
QStringList files;
|
||||||
|
foreach (IDocument *document, documents)
|
||||||
|
files << document->fileName();
|
||||||
|
initDialog(files);
|
||||||
|
}
|
||||||
|
|
||||||
|
ReadOnlyFilesDialog::~ReadOnlyFilesDialog()
|
||||||
|
{
|
||||||
|
delete ui;
|
||||||
|
delete d;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*!
|
||||||
|
* \brief Set a user defined message in the dialog.
|
||||||
|
* \internal
|
||||||
|
*/
|
||||||
|
void ReadOnlyFilesDialog::setMessage(const QString &message)
|
||||||
|
{
|
||||||
|
ui->msgLabel->setText(message);
|
||||||
|
}
|
||||||
|
|
||||||
|
/*!
|
||||||
|
* \brief Enable the error output to the user via a messageBox.
|
||||||
|
* \param warning Added to the dialog, should show possible consequences if the file is still read only.
|
||||||
|
* \internal
|
||||||
|
*/
|
||||||
|
void ReadOnlyFilesDialog::setShowFailWarning(bool show, const QString &warning)
|
||||||
|
{
|
||||||
|
d->showWarnings = show;
|
||||||
|
d->failWarning = warning;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*!
|
||||||
|
* \brief Opens a message box with an error description according to the type.
|
||||||
|
* \internal
|
||||||
|
*/
|
||||||
|
void ReadOnlyFilesDialog::promptFailWarning(const QStringList &files, ReadOnlyResult type) const
|
||||||
|
{
|
||||||
|
if (files.isEmpty())
|
||||||
|
return;
|
||||||
|
QString title;
|
||||||
|
QString message;
|
||||||
|
QString details;
|
||||||
|
if (files.count() == 1) {
|
||||||
|
const QString file = files.first();
|
||||||
|
switch (type) {
|
||||||
|
case RO_OpenVCS: {
|
||||||
|
if (IVersionControl *vc = d->versionControls[file]) {
|
||||||
|
const QString openText = vc->vcsOpenText().remove(QLatin1Char('&'));
|
||||||
|
title = tr("Failed To: %1 File").arg(openText);
|
||||||
|
message = tr("%1 file %2 from version control system %3 failed.\n")
|
||||||
|
.arg(openText)
|
||||||
|
.arg(QDir::toNativeSeparators(file))
|
||||||
|
.arg(vc->displayName());
|
||||||
|
message += d->failWarning;
|
||||||
|
} else {
|
||||||
|
title = tr("No Version Control System Found");
|
||||||
|
message = tr("Cannot open file %1 from version control system.\n"
|
||||||
|
"No version control system found.\n")
|
||||||
|
.arg(QDir::toNativeSeparators(file));
|
||||||
|
message += d->failWarning;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case RO_MakeWritable:
|
||||||
|
title = tr("Cannot Set Permissions");
|
||||||
|
message = tr("Cannot set permissions for %1 to writable.\n")
|
||||||
|
.arg(QDir::toNativeSeparators(file));
|
||||||
|
message += d->failWarning;
|
||||||
|
break;
|
||||||
|
case RO_SaveAs:
|
||||||
|
title = tr("Cannot Save File");
|
||||||
|
message = tr("Cannot save file %1\n").arg(QDir::toNativeSeparators(file));
|
||||||
|
message += d->failWarning;
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
title = tr("Canceled Changing Permissions!");
|
||||||
|
message = d->failWarning;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
title = tr("Could Not Change Permissions On Some Files!");
|
||||||
|
message = d->failWarning;
|
||||||
|
message += tr("\nSee details for a complete list of files.");
|
||||||
|
details = files.join(QLatin1String("\n"));
|
||||||
|
}
|
||||||
|
QMessageBox msgBox(QMessageBox::Warning, title, message);
|
||||||
|
msgBox.setDetailedText(details);
|
||||||
|
msgBox.exec();
|
||||||
|
}
|
||||||
|
|
||||||
|
/*!
|
||||||
|
* \brief Executes the dialog.
|
||||||
|
* \return ReadOnlyResult which gives information about the operation which was used to make the files writable.
|
||||||
|
* \internal
|
||||||
|
*
|
||||||
|
* Also displays an error dialog when some operations can't be executed and the function
|
||||||
|
* setShowFailWarning was called.
|
||||||
|
*/
|
||||||
|
int ReadOnlyFilesDialog::exec()
|
||||||
|
{
|
||||||
|
if (QDialog::exec() != QDialog::Accepted)
|
||||||
|
return RO_Cancel;
|
||||||
|
|
||||||
|
ReadOnlyResult result;
|
||||||
|
QStringList failedToMakeWritable;
|
||||||
|
foreach (ReadOnlyFilesDialogPrivate::ButtonGroupForFile buttengroup, d->buttonGroups) {
|
||||||
|
result = static_cast<ReadOnlyResult>(buttengroup.group->checkedId());
|
||||||
|
switch (result) {
|
||||||
|
case RO_MakeWritable:
|
||||||
|
if (!Utils::FileUtils::makeWritable(Utils::FileName(QFileInfo(buttengroup.fileName)))) {
|
||||||
|
failedToMakeWritable << buttengroup.fileName;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case RO_OpenVCS:
|
||||||
|
if (!d->versionControls[buttengroup.fileName]->vcsOpen(buttengroup.fileName)) {
|
||||||
|
failedToMakeWritable << buttengroup.fileName;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case RO_SaveAs:
|
||||||
|
if (!EditorManager::instance()->saveDocumentAs(d->document)) {
|
||||||
|
failedToMakeWritable << buttengroup.fileName;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
failedToMakeWritable << buttengroup.fileName;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
if (!QFileInfo(buttengroup.fileName).isWritable())
|
||||||
|
failedToMakeWritable << buttengroup.fileName;
|
||||||
|
}
|
||||||
|
if (!failedToMakeWritable.isEmpty()) {
|
||||||
|
if (d->showWarnings)
|
||||||
|
promptFailWarning(failedToMakeWritable, result);
|
||||||
|
}
|
||||||
|
return failedToMakeWritable.isEmpty() ? result : RO_Cancel;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*!
|
||||||
|
* \brief Creates a radio button in the column specified with type.
|
||||||
|
* \param group the created button will be added to this group.
|
||||||
|
* \return the created button.
|
||||||
|
* \internal
|
||||||
|
*/
|
||||||
|
QRadioButton* ReadOnlyFilesDialog::createRadioButtonForItem(QTreeWidgetItem *item, QButtonGroup *group,
|
||||||
|
ReadOnlyFilesDialog::ReadOnlyFilesTreeColumn type)
|
||||||
|
|
||||||
|
{
|
||||||
|
QRadioButton *radioButton = new QRadioButton(this);
|
||||||
|
group->addButton(radioButton, type);
|
||||||
|
item->setTextAlignment(type, Qt::AlignHCenter);
|
||||||
|
ui->treeWidget->setItemWidget(item, type, radioButton);
|
||||||
|
return radioButton;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*!
|
||||||
|
* \brief Checks the type of the select all combo box and change the user selection per file accordingly.
|
||||||
|
* \internal
|
||||||
|
*/
|
||||||
|
void ReadOnlyFilesDialog::setAll(int index)
|
||||||
|
{
|
||||||
|
// If mixed is the current index, no need to change the user selection.
|
||||||
|
if (index == d->setAllIndexForOperation[-1/*mixed*/])
|
||||||
|
return;
|
||||||
|
|
||||||
|
// Get the selected type from the select all combo box.
|
||||||
|
ReadOnlyFilesTreeColumn type;
|
||||||
|
if (index == d->setAllIndexForOperation[MakeWritable])
|
||||||
|
type = MakeWritable;
|
||||||
|
else if (index == d->setAllIndexForOperation[OpenWithVCS])
|
||||||
|
type = OpenWithVCS;
|
||||||
|
else if (index == d->setAllIndexForOperation[SaveAs])
|
||||||
|
type = SaveAs;
|
||||||
|
|
||||||
|
// Check for every file if the selected operation is available and change it to the operation.
|
||||||
|
foreach (ReadOnlyFilesDialogPrivate::ButtonGroupForFile groupForFile, d->buttonGroups) {
|
||||||
|
QRadioButton *radioButton = qobject_cast<QRadioButton*> (groupForFile.group->button(type));
|
||||||
|
if (radioButton)
|
||||||
|
radioButton->setChecked(true);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/*!
|
||||||
|
* \brief Updates the select all combo box depending on the selection in the tree widget the user made.
|
||||||
|
* \internal
|
||||||
|
*/
|
||||||
|
void ReadOnlyFilesDialog::updateSelectAll()
|
||||||
|
{
|
||||||
|
int selectedOperation = -1;
|
||||||
|
foreach (ReadOnlyFilesDialogPrivate::ButtonGroupForFile groupForFile, d->buttonGroups) {
|
||||||
|
if (selectedOperation == -1) {
|
||||||
|
selectedOperation = groupForFile.group->checkedId();
|
||||||
|
} else if (selectedOperation != groupForFile.group->checkedId()) {
|
||||||
|
ui->setAll->setCurrentIndex(0);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
ui->setAll->setCurrentIndex(d->setAllIndexForOperation[selectedOperation]);
|
||||||
|
}
|
||||||
|
|
||||||
|
/*!
|
||||||
|
* \brief Adds files to the dialog and check for possible operation to make the file writable.
|
||||||
|
* \param fileNames A List of files which should be added to the dialog.
|
||||||
|
* \internal
|
||||||
|
*/
|
||||||
|
void ReadOnlyFilesDialog::initDialog(const QStringList &fileNames)
|
||||||
|
{
|
||||||
|
ui->setupUi(this);
|
||||||
|
ui->buttonBox->addButton(tr("&Change Permission"), QDialogButtonBox::AcceptRole);
|
||||||
|
ui->buttonBox->addButton(QDialogButtonBox::Cancel);
|
||||||
|
|
||||||
|
QString vcsOpenTextForAll;
|
||||||
|
QString vcsMakeWritableTextForAll;
|
||||||
|
bool useMakeWritable = false;
|
||||||
|
foreach (const QString &fileName, fileNames) {
|
||||||
|
const QFileInfo info = QFileInfo(fileName);
|
||||||
|
const QString visibleName = info.fileName();
|
||||||
|
const QString directory = info.absolutePath();
|
||||||
|
|
||||||
|
// Setup a default entry with filename folder and make writable radio button.
|
||||||
|
QTreeWidgetItem *item = new QTreeWidgetItem(ui->treeWidget);
|
||||||
|
item->setText(FileName, visibleName);
|
||||||
|
item->setIcon(FileName, FileIconProvider::instance()->icon(QFileInfo(fileName)));
|
||||||
|
item->setText(Folder, Utils::FileUtils::shortNativePath(Utils::FileName(QFileInfo(directory))));
|
||||||
|
QButtonGroup *radioButtonGroup = new QButtonGroup;
|
||||||
|
|
||||||
|
// Add a button for opening the file with a version control system
|
||||||
|
// if the file is managed by an version control system which allows opening files.
|
||||||
|
IVersionControl *versionControlForFile =
|
||||||
|
ICore::vcsManager()->findVersionControlForDirectory(directory);
|
||||||
|
const bool fileManagedByVCS = versionControlForFile
|
||||||
|
&& versionControlForFile->openSupportMode() != IVersionControl::NoOpen;
|
||||||
|
if (fileManagedByVCS) {
|
||||||
|
const QString vcsOpenTextForFile =
|
||||||
|
versionControlForFile->vcsOpenText().remove(QLatin1Char('&'));
|
||||||
|
const QString vcsMakeWritableTextforFile =
|
||||||
|
versionControlForFile->vcsMakeWritableText().remove(QLatin1Char('&'));
|
||||||
|
if (!d->useVCS) {
|
||||||
|
vcsOpenTextForAll = vcsOpenTextForFile;
|
||||||
|
vcsMakeWritableTextForAll = vcsMakeWritableTextforFile;
|
||||||
|
d->useVCS = true;
|
||||||
|
} else {
|
||||||
|
// If there are different open or make writable texts choose the default one.
|
||||||
|
if (vcsOpenTextForFile != vcsOpenTextForAll)
|
||||||
|
vcsOpenTextForAll.clear();
|
||||||
|
if (vcsMakeWritableTextforFile != vcsMakeWritableTextForAll)
|
||||||
|
vcsMakeWritableTextForAll.clear();
|
||||||
|
}
|
||||||
|
// Add make writable if it is supported by the reposetory.
|
||||||
|
if (versionControlForFile->openSupportMode() == IVersionControl::OpenOptional) {
|
||||||
|
useMakeWritable = true;
|
||||||
|
createRadioButtonForItem(item, radioButtonGroup, MakeWritable);
|
||||||
|
}
|
||||||
|
createRadioButtonForItem(item, radioButtonGroup, OpenWithVCS)->setChecked(true);
|
||||||
|
} else {
|
||||||
|
useMakeWritable = true;
|
||||||
|
createRadioButtonForItem(item, radioButtonGroup, MakeWritable)->setChecked(true);
|
||||||
|
}
|
||||||
|
// Add a Save As radio button if requested.
|
||||||
|
if (d->useSaveAs)
|
||||||
|
createRadioButtonForItem(item, radioButtonGroup, SaveAs);
|
||||||
|
// If the file is managed by a version control system save the vcs for this file.
|
||||||
|
d->versionControls[fileName] = fileManagedByVCS ? versionControlForFile : 0;
|
||||||
|
|
||||||
|
// Also save the buttongroup for every file to get the result for each entry.
|
||||||
|
ReadOnlyFilesDialogPrivate::ButtonGroupForFile groupForFile;
|
||||||
|
groupForFile.fileName = fileName;
|
||||||
|
groupForFile.group = radioButtonGroup;
|
||||||
|
d->buttonGroups.append(groupForFile);
|
||||||
|
connect(radioButtonGroup, SIGNAL(buttonClicked(int)), this, SLOT(updateSelectAll()));
|
||||||
|
}
|
||||||
|
|
||||||
|
// Apply the Mac file dialog style.
|
||||||
|
if (Utils::HostOsInfo::isMacHost())
|
||||||
|
ui->treeWidget->setAlternatingRowColors(true);
|
||||||
|
|
||||||
|
// Do not show any options to the user if he has no choice.
|
||||||
|
if (!d->useSaveAs && (!d->useVCS || !useMakeWritable)) {
|
||||||
|
ui->treeWidget->setColumnHidden(MakeWritable, true);
|
||||||
|
ui->treeWidget->setColumnHidden(OpenWithVCS, true);
|
||||||
|
ui->treeWidget->setColumnHidden(SaveAs, true);
|
||||||
|
ui->treeWidget->resizeColumnToContents(FileName);
|
||||||
|
ui->treeWidget->resizeColumnToContents(Folder);
|
||||||
|
ui->setAll->setVisible(false);
|
||||||
|
ui->setAllLabel->setVisible(false);
|
||||||
|
ui->verticalLayout->removeItem(ui->setAllLayout);
|
||||||
|
if (d->useVCS)
|
||||||
|
ui->msgLabel->setText(tr("The following files are not checked out by now.\n"
|
||||||
|
"Do you want to check out these files now?"));
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// If there is just one file entry, there is no need to show the select all combo box
|
||||||
|
if (fileNames.count() < 2) {
|
||||||
|
ui->setAll->setVisible(false);
|
||||||
|
ui->setAllLabel->setVisible(false);
|
||||||
|
ui->verticalLayout->removeItem(ui->setAllLayout);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Add items to the Set all combo box.
|
||||||
|
ui->setAll->addItem(d->mixedText);
|
||||||
|
d->setAllIndexForOperation[-1/*mixed*/] = ui->setAll->count() - 1;
|
||||||
|
if (d->useVCS) {
|
||||||
|
// If the files are managed by just one version control system, the Open and Make Writable
|
||||||
|
// text for the specific system is used.
|
||||||
|
if (!vcsOpenTextForAll.isEmpty() && vcsOpenTextForAll != d->versionControlOpenText) {
|
||||||
|
d->versionControlOpenText = vcsOpenTextForAll;
|
||||||
|
ui->treeWidget->headerItem()->setText(OpenWithVCS, d->versionControlOpenText);
|
||||||
|
}
|
||||||
|
if (!vcsMakeWritableTextForAll.isEmpty() && vcsMakeWritableTextForAll != d->makeWritableText) {
|
||||||
|
d->makeWritableText = vcsMakeWritableTextForAll;
|
||||||
|
ui->treeWidget->headerItem()->setText(MakeWritable, d->makeWritableText);
|
||||||
|
}
|
||||||
|
ui->setAll->addItem(d->versionControlOpenText);
|
||||||
|
ui->setAll->setCurrentIndex(ui->setAll->count() - 1);
|
||||||
|
d->setAllIndexForOperation[OpenWithVCS] = ui->setAll->count() - 1;
|
||||||
|
}
|
||||||
|
if (useMakeWritable) {
|
||||||
|
ui->setAll->addItem(d->makeWritableText);
|
||||||
|
d->setAllIndexForOperation[MakeWritable] = ui->setAll->count() - 1;
|
||||||
|
if (ui->setAll->currentIndex() == -1)
|
||||||
|
ui->setAll->setCurrentIndex(ui->setAll->count() - 1);
|
||||||
|
}
|
||||||
|
if (d->useSaveAs) {
|
||||||
|
ui->setAll->addItem(d->saveAsText);
|
||||||
|
d->setAllIndexForOperation[SaveAs] = ui->setAll->count() - 1;
|
||||||
|
}
|
||||||
|
connect(ui->setAll, SIGNAL(activated(int)), this, SLOT(setAll(int)));
|
||||||
|
|
||||||
|
// Filter which columns should be visible and resize them to content.
|
||||||
|
for (int i = 0; i < NumberOfColumns; ++i) {
|
||||||
|
if ((i == SaveAs && !d->useSaveAs) || (i == OpenWithVCS && !d->useVCS)
|
||||||
|
|| (i == MakeWritable && !useMakeWritable)) {
|
||||||
|
ui->treeWidget->setColumnHidden(i, true);
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
ui->treeWidget->resizeColumnToContents(i);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}// namespace Internal
|
||||||
|
}// namespace Core
|
109
src/plugins/coreplugin/dialogs/readonlyfilesdialog.h
Normal file
109
src/plugins/coreplugin/dialogs/readonlyfilesdialog.h
Normal file
@@ -0,0 +1,109 @@
|
|||||||
|
/****************************************************************************
|
||||||
|
**
|
||||||
|
** Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies).
|
||||||
|
** Contact: http://www.qt-project.org/legal
|
||||||
|
**
|
||||||
|
** This file is part of Qt Creator.
|
||||||
|
**
|
||||||
|
** Commercial License Usage
|
||||||
|
** Licensees holding valid commercial Qt licenses may use this file in
|
||||||
|
** accordance with the commercial license agreement provided with the
|
||||||
|
** Software or, alternatively, in accordance with the terms contained in
|
||||||
|
** a written agreement between you and Digia. For licensing terms and
|
||||||
|
** conditions see http://qt.digia.com/licensing. For further information
|
||||||
|
** use the contact form at http://qt.digia.com/contact-us.
|
||||||
|
**
|
||||||
|
** GNU Lesser General Public License Usage
|
||||||
|
** Alternatively, this file may be used under the terms of the GNU Lesser
|
||||||
|
** General Public License version 2.1 as published by the Free Software
|
||||||
|
** Foundation and appearing in the file LICENSE.LGPL included in the
|
||||||
|
** packaging of this file. Please review the following information to
|
||||||
|
** ensure the GNU Lesser General Public License version 2.1 requirements
|
||||||
|
** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
|
||||||
|
**
|
||||||
|
** In addition, as a special exception, Digia gives you certain additional
|
||||||
|
** rights. These rights are described in the Digia Qt LGPL Exception
|
||||||
|
** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
|
||||||
|
**
|
||||||
|
****************************************************************************/
|
||||||
|
|
||||||
|
#ifndef READONLYFILESDIALOG_H
|
||||||
|
#define READONLYFILESDIALOG_H
|
||||||
|
|
||||||
|
#include <coreplugin/core_global.h>
|
||||||
|
|
||||||
|
#include <QDialog>
|
||||||
|
#include <QHash>
|
||||||
|
|
||||||
|
QT_BEGIN_NAMESPACE
|
||||||
|
class QButtonGroup;
|
||||||
|
class QTreeWidgetItem;
|
||||||
|
class QRadioButton;
|
||||||
|
QT_END_NAMESPACE
|
||||||
|
|
||||||
|
namespace Core {
|
||||||
|
class IVersionControl;
|
||||||
|
class IDocument;
|
||||||
|
|
||||||
|
namespace Internal {
|
||||||
|
|
||||||
|
namespace Ui { class ReadOnlyFilesDialog; }
|
||||||
|
|
||||||
|
class CORE_EXPORT ReadOnlyFilesDialog : public QDialog
|
||||||
|
{
|
||||||
|
Q_OBJECT
|
||||||
|
|
||||||
|
private:
|
||||||
|
enum ReadOnlyFilesTreeColumn {
|
||||||
|
MakeWritable = 0,
|
||||||
|
OpenWithVCS = 1,
|
||||||
|
SaveAs = 2,
|
||||||
|
FileName = 3,
|
||||||
|
Folder = 4,
|
||||||
|
NumberOfColumns
|
||||||
|
};
|
||||||
|
|
||||||
|
public:
|
||||||
|
enum ReadOnlyResult {
|
||||||
|
RO_Cancel = -1,
|
||||||
|
RO_OpenVCS = OpenWithVCS,
|
||||||
|
RO_MakeWritable = MakeWritable,
|
||||||
|
RO_SaveAs = SaveAs
|
||||||
|
};
|
||||||
|
|
||||||
|
explicit ReadOnlyFilesDialog(const QList<QString> &fileNames,
|
||||||
|
QWidget *parent = 0);
|
||||||
|
explicit ReadOnlyFilesDialog(const QString &fileName,
|
||||||
|
QWidget * parent = 0);
|
||||||
|
explicit ReadOnlyFilesDialog(IDocument *document,
|
||||||
|
QWidget * parent = 0,
|
||||||
|
bool displaySaveAs = false);
|
||||||
|
explicit ReadOnlyFilesDialog(const QList<IDocument *> documents,
|
||||||
|
QWidget * parent = 0);
|
||||||
|
|
||||||
|
~ReadOnlyFilesDialog();
|
||||||
|
|
||||||
|
void setMessage(const QString &message);
|
||||||
|
void setShowFailWarning(bool show, const QString &warning = QString());
|
||||||
|
|
||||||
|
int exec();
|
||||||
|
|
||||||
|
private:
|
||||||
|
void initDialog(const QStringList &fileNames);
|
||||||
|
void promptFailWarning(const QStringList &files, ReadOnlyResult type) const;
|
||||||
|
QRadioButton *createRadioButtonForItem(QTreeWidgetItem *item, QButtonGroup *group,
|
||||||
|
ReadOnlyFilesDialog::ReadOnlyFilesTreeColumn type);
|
||||||
|
|
||||||
|
private slots:
|
||||||
|
void setAll(int index);
|
||||||
|
void updateSelectAll();
|
||||||
|
|
||||||
|
private:
|
||||||
|
class ReadOnlyFilesDialogPrivate *d;
|
||||||
|
Ui::ReadOnlyFilesDialog *ui;
|
||||||
|
};
|
||||||
|
|
||||||
|
} // namespace Internal
|
||||||
|
} // namespace Core
|
||||||
|
|
||||||
|
#endif // READONLYFILESDIALOG_H
|
145
src/plugins/coreplugin/dialogs/readonlyfilesdialog.ui
Normal file
145
src/plugins/coreplugin/dialogs/readonlyfilesdialog.ui
Normal file
@@ -0,0 +1,145 @@
|
|||||||
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
|
<ui version="4.0">
|
||||||
|
<class>Core::Internal::ReadOnlyFilesDialog</class>
|
||||||
|
<widget class="QDialog" name="Core::Internal::ReadOnlyFilesDialog">
|
||||||
|
<property name="geometry">
|
||||||
|
<rect>
|
||||||
|
<x>0</x>
|
||||||
|
<y>0</y>
|
||||||
|
<width>639</width>
|
||||||
|
<height>217</height>
|
||||||
|
</rect>
|
||||||
|
</property>
|
||||||
|
<property name="windowTitle">
|
||||||
|
<string>Files Without Write Permissions</string>
|
||||||
|
</property>
|
||||||
|
<layout class="QVBoxLayout" name="verticalLayout">
|
||||||
|
<item>
|
||||||
|
<widget class="QLabel" name="msgLabel">
|
||||||
|
<property name="text">
|
||||||
|
<string>The following files have no write permissions. Do you want to change the permissions?</string>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
<item>
|
||||||
|
<widget class="QTreeWidget" name="treeWidget">
|
||||||
|
<property name="selectionMode">
|
||||||
|
<enum>QAbstractItemView::NoSelection</enum>
|
||||||
|
</property>
|
||||||
|
<property name="textElideMode">
|
||||||
|
<enum>Qt::ElideLeft</enum>
|
||||||
|
</property>
|
||||||
|
<property name="indentation">
|
||||||
|
<number>0</number>
|
||||||
|
</property>
|
||||||
|
<property name="uniformRowHeights">
|
||||||
|
<bool>true</bool>
|
||||||
|
</property>
|
||||||
|
<property name="itemsExpandable">
|
||||||
|
<bool>false</bool>
|
||||||
|
</property>
|
||||||
|
<property name="columnCount">
|
||||||
|
<number>5</number>
|
||||||
|
</property>
|
||||||
|
<column>
|
||||||
|
<property name="text">
|
||||||
|
<string>Make Writeable</string>
|
||||||
|
</property>
|
||||||
|
</column>
|
||||||
|
<column>
|
||||||
|
<property name="text">
|
||||||
|
<string>Open With VCS</string>
|
||||||
|
</property>
|
||||||
|
</column>
|
||||||
|
<column>
|
||||||
|
<property name="text">
|
||||||
|
<string>Save As</string>
|
||||||
|
</property>
|
||||||
|
</column>
|
||||||
|
<column>
|
||||||
|
<property name="text">
|
||||||
|
<string notr="true">File Name</string>
|
||||||
|
</property>
|
||||||
|
</column>
|
||||||
|
<column>
|
||||||
|
<property name="text">
|
||||||
|
<string>Path</string>
|
||||||
|
</property>
|
||||||
|
</column>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
<item>
|
||||||
|
<layout class="QHBoxLayout" name="setAllLayout">
|
||||||
|
<item>
|
||||||
|
<widget class="QLabel" name="setAllLabel">
|
||||||
|
<property name="text">
|
||||||
|
<string>Select all, if possible: </string>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
<item>
|
||||||
|
<widget class="QComboBox" name="setAll"/>
|
||||||
|
</item>
|
||||||
|
<item>
|
||||||
|
<spacer name="horizontalSpacer">
|
||||||
|
<property name="orientation">
|
||||||
|
<enum>Qt::Horizontal</enum>
|
||||||
|
</property>
|
||||||
|
<property name="sizeHint" stdset="0">
|
||||||
|
<size>
|
||||||
|
<width>40</width>
|
||||||
|
<height>20</height>
|
||||||
|
</size>
|
||||||
|
</property>
|
||||||
|
</spacer>
|
||||||
|
</item>
|
||||||
|
</layout>
|
||||||
|
</item>
|
||||||
|
<item>
|
||||||
|
<widget class="QDialogButtonBox" name="buttonBox">
|
||||||
|
<property name="orientation">
|
||||||
|
<enum>Qt::Horizontal</enum>
|
||||||
|
</property>
|
||||||
|
<property name="standardButtons">
|
||||||
|
<set>QDialogButtonBox::NoButton</set>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
</layout>
|
||||||
|
</widget>
|
||||||
|
<resources/>
|
||||||
|
<connections>
|
||||||
|
<connection>
|
||||||
|
<sender>buttonBox</sender>
|
||||||
|
<signal>accepted()</signal>
|
||||||
|
<receiver>Core::Internal::ReadOnlyFilesDialog</receiver>
|
||||||
|
<slot>accept()</slot>
|
||||||
|
<hints>
|
||||||
|
<hint type="sourcelabel">
|
||||||
|
<x>248</x>
|
||||||
|
<y>254</y>
|
||||||
|
</hint>
|
||||||
|
<hint type="destinationlabel">
|
||||||
|
<x>157</x>
|
||||||
|
<y>274</y>
|
||||||
|
</hint>
|
||||||
|
</hints>
|
||||||
|
</connection>
|
||||||
|
<connection>
|
||||||
|
<sender>buttonBox</sender>
|
||||||
|
<signal>rejected()</signal>
|
||||||
|
<receiver>Core::Internal::ReadOnlyFilesDialog</receiver>
|
||||||
|
<slot>reject()</slot>
|
||||||
|
<hints>
|
||||||
|
<hint type="sourcelabel">
|
||||||
|
<x>316</x>
|
||||||
|
<y>260</y>
|
||||||
|
</hint>
|
||||||
|
<hint type="destinationlabel">
|
||||||
|
<x>286</x>
|
||||||
|
<y>274</y>
|
||||||
|
</hint>
|
||||||
|
</hints>
|
||||||
|
</connection>
|
||||||
|
</connections>
|
||||||
|
</ui>
|
@@ -35,11 +35,12 @@
|
|||||||
#include "ieditorfactory.h"
|
#include "ieditorfactory.h"
|
||||||
#include "iexternaleditor.h"
|
#include "iexternaleditor.h"
|
||||||
#include "idocument.h"
|
#include "idocument.h"
|
||||||
#include "iversioncontrol.h"
|
|
||||||
#include "mimedatabase.h"
|
#include "mimedatabase.h"
|
||||||
#include "saveitemsdialog.h"
|
#include "saveitemsdialog.h"
|
||||||
#include "coreconstants.h"
|
#include "coreconstants.h"
|
||||||
|
|
||||||
|
#include "dialogs/readonlyfilesdialog.h"
|
||||||
|
|
||||||
#include <utils/hostosinfo.h>
|
#include <utils/hostosinfo.h>
|
||||||
#include <utils/qtcassert.h>
|
#include <utils/qtcassert.h>
|
||||||
#include <utils/pathchooser.h>
|
#include <utils/pathchooser.h>
|
||||||
@@ -58,7 +59,6 @@
|
|||||||
#include <QMainWindow>
|
#include <QMainWindow>
|
||||||
#include <QMenu>
|
#include <QMenu>
|
||||||
#include <QMessageBox>
|
#include <QMessageBox>
|
||||||
#include <QPushButton>
|
|
||||||
|
|
||||||
/*!
|
/*!
|
||||||
\class Core::DocumentManager
|
\class Core::DocumentManager
|
||||||
@@ -565,7 +565,9 @@ void DocumentManager::unexpectFileChange(const QString &fileName)
|
|||||||
\fn QList<IDocument*> DocumentManager::saveModifiedFilesSilently(const QList<IDocument*> &documents)
|
\fn QList<IDocument*> DocumentManager::saveModifiedFilesSilently(const QList<IDocument*> &documents)
|
||||||
|
|
||||||
Tries to save the files listed in \a documents. The \a cancelled argument is set to true
|
Tries to save the files listed in \a documents. The \a cancelled argument is set to true
|
||||||
if the user cancelled the dialog. Returns the files that could not be saved.
|
if the user cancelled the dialog. Returns the files that could not be saved. If the files
|
||||||
|
listed in documents have no write permissions an additional dialog will be prompted to
|
||||||
|
query the user for these permissions.
|
||||||
*/
|
*/
|
||||||
QList<IDocument *> DocumentManager::saveModifiedDocumentsSilently(const QList<IDocument *> &documents, bool *cancelled)
|
QList<IDocument *> DocumentManager::saveModifiedDocumentsSilently(const QList<IDocument *> &documents, bool *cancelled)
|
||||||
{
|
{
|
||||||
@@ -581,7 +583,8 @@ QList<IDocument *> DocumentManager::saveModifiedDocumentsSilently(const QList<ID
|
|||||||
of modified files (in this context).
|
of modified files (in this context).
|
||||||
The \a cancelled argument is set to true if the user cancelled the dialog,
|
The \a cancelled argument is set to true if the user cancelled the dialog,
|
||||||
\a alwaysSave is set to match the selection of the user, if files should
|
\a alwaysSave is set to match the selection of the user, if files should
|
||||||
always automatically be saved.
|
always automatically be saved. If the files listed in documents have no write
|
||||||
|
permissions an additional dialog will be prompted to query the user for these permissions.
|
||||||
Returns the files that have not been saved.
|
Returns the files that have not been saved.
|
||||||
*/
|
*/
|
||||||
QList<IDocument *> DocumentManager::saveModifiedDocuments(const QList<IDocument *> &documents,
|
QList<IDocument *> DocumentManager::saveModifiedDocuments(const QList<IDocument *> &documents,
|
||||||
@@ -642,7 +645,25 @@ static QList<IDocument *> saveModifiedFilesHelper(const QList<IDocument *> &docu
|
|||||||
*alwaysSave = dia.alwaysSaveChecked();
|
*alwaysSave = dia.alwaysSaveChecked();
|
||||||
documentsToSave = dia.itemsToSave();
|
documentsToSave = dia.itemsToSave();
|
||||||
}
|
}
|
||||||
|
// Check for files without write permissions.
|
||||||
|
QList<IDocument *> roDocuments;
|
||||||
|
foreach (IDocument *document, documentsToSave) {
|
||||||
|
if (document->isFileReadOnly())
|
||||||
|
roDocuments << document;
|
||||||
|
}
|
||||||
|
if (!roDocuments.isEmpty()) {
|
||||||
|
Core::Internal::ReadOnlyFilesDialog roDialog(roDocuments, d->m_mainWindow);
|
||||||
|
roDialog.setShowFailWarning(true, QCoreApplication::translate(
|
||||||
|
"saveModifiedFilesHelper",
|
||||||
|
"Could not save the files.",
|
||||||
|
"error message"));
|
||||||
|
if (roDialog.exec() == Core::Internal::ReadOnlyFilesDialog::RO_Cancel) {
|
||||||
|
if (cancelled)
|
||||||
|
(*cancelled) = true;
|
||||||
|
notSaved = modifiedDocuments;
|
||||||
|
return notSaved;
|
||||||
|
}
|
||||||
|
}
|
||||||
foreach (IDocument *document, documentsToSave) {
|
foreach (IDocument *document, documentsToSave) {
|
||||||
if (!EditorManager::instance()->saveDocument(document)) {
|
if (!EditorManager::instance()->saveDocument(document)) {
|
||||||
if (cancelled)
|
if (cancelled)
|
||||||
@@ -742,7 +763,7 @@ QString DocumentManager::getSaveFileNameWithExtension(const QString &title, cons
|
|||||||
|
|
||||||
Asks the user for a new file name (Save File As) for /arg document.
|
Asks the user for a new file name (Save File As) for /arg document.
|
||||||
*/
|
*/
|
||||||
QString DocumentManager::getSaveAsFileName(IDocument *document, const QString &filter, QString *selectedFilter)
|
QString DocumentManager::getSaveAsFileName(const IDocument *document, const QString &filter, QString *selectedFilter)
|
||||||
{
|
{
|
||||||
if (!document)
|
if (!document)
|
||||||
return QLatin1String("");
|
return QLatin1String("");
|
||||||
@@ -804,61 +825,6 @@ QStringList DocumentManager::getOpenFileNames(const QString &filters,
|
|||||||
return files;
|
return files;
|
||||||
}
|
}
|
||||||
|
|
||||||
DocumentManager::ReadOnlyAction
|
|
||||||
DocumentManager::promptReadOnlyFile(const QString &fileName,
|
|
||||||
const IVersionControl *versionControl,
|
|
||||||
QWidget *parent,
|
|
||||||
bool displaySaveAsButton)
|
|
||||||
{
|
|
||||||
// Version Control: If automatic open is desired, open right away.
|
|
||||||
bool promptVCS = false;
|
|
||||||
if (versionControl && versionControl->openSupportMode() != IVersionControl::NoOpen) {
|
|
||||||
if (versionControl->settingsFlags() & IVersionControl::AutoOpen)
|
|
||||||
return RO_OpenVCS;
|
|
||||||
promptVCS = true;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Create message box.
|
|
||||||
QMessageBox msgBox(QMessageBox::Question, tr("File Is Read Only"),
|
|
||||||
tr("The file <i>%1</i> is read only.").arg(QDir::toNativeSeparators(fileName)),
|
|
||||||
QMessageBox::Cancel, parent);
|
|
||||||
|
|
||||||
QPushButton *vcsButton = 0;
|
|
||||||
if (promptVCS) {
|
|
||||||
vcsButton = msgBox.addButton(versionControl->vcsOpenText(), QMessageBox::AcceptRole);
|
|
||||||
}
|
|
||||||
|
|
||||||
QString makeWritableText;
|
|
||||||
QPushButton *makeWritableButton = 0;
|
|
||||||
// If the VCS has OpenMandatory we don't show "Make Writable"
|
|
||||||
if (versionControl->openSupportMode() != IVersionControl::OpenMandatory) {
|
|
||||||
makeWritableText = versionControl->vcsMakeWritableText();
|
|
||||||
if (makeWritableText.isEmpty())
|
|
||||||
makeWritableText = tr("Make &Writable");
|
|
||||||
makeWritableButton = msgBox.addButton(makeWritableText, QMessageBox::AcceptRole);
|
|
||||||
}
|
|
||||||
|
|
||||||
QPushButton *saveAsButton = 0;
|
|
||||||
if (displaySaveAsButton)
|
|
||||||
saveAsButton = msgBox.addButton(tr("&Save As..."), QMessageBox::ActionRole);
|
|
||||||
|
|
||||||
if (vcsButton)
|
|
||||||
msgBox.setDefaultButton(vcsButton);
|
|
||||||
else if (makeWritableButton)
|
|
||||||
msgBox.setDefaultButton(makeWritableButton);
|
|
||||||
|
|
||||||
msgBox.exec();
|
|
||||||
|
|
||||||
QAbstractButton *clickedButton = msgBox.clickedButton();
|
|
||||||
if (clickedButton == vcsButton)
|
|
||||||
return RO_OpenVCS;
|
|
||||||
if (clickedButton == makeWritableButton)
|
|
||||||
return RO_MakeWriteable;
|
|
||||||
if (displaySaveAsButton && clickedButton == saveAsButton)
|
|
||||||
return RO_SaveAs;
|
|
||||||
return RO_Cancel;
|
|
||||||
}
|
|
||||||
|
|
||||||
void DocumentManager::changedFile(const QString &fileName)
|
void DocumentManager::changedFile(const QString &fileName)
|
||||||
{
|
{
|
||||||
const bool wasempty = d->m_changedFiles.isEmpty();
|
const bool wasempty = d->m_changedFiles.isEmpty();
|
||||||
|
@@ -46,7 +46,6 @@ namespace Core {
|
|||||||
|
|
||||||
class IContext;
|
class IContext;
|
||||||
class IDocument;
|
class IDocument;
|
||||||
class IVersionControl;
|
|
||||||
|
|
||||||
class CORE_EXPORT DocumentManager : public QObject
|
class CORE_EXPORT DocumentManager : public QObject
|
||||||
{
|
{
|
||||||
@@ -98,7 +97,7 @@ public:
|
|||||||
const QString &filter = QString(), QString *selectedFilter = 0);
|
const QString &filter = QString(), QString *selectedFilter = 0);
|
||||||
static QString getSaveFileNameWithExtension(const QString &title, const QString &pathIn,
|
static QString getSaveFileNameWithExtension(const QString &title, const QString &pathIn,
|
||||||
const QString &filter);
|
const QString &filter);
|
||||||
static QString getSaveAsFileName(IDocument *document, const QString &filter = QString(),
|
static QString getSaveAsFileName(const IDocument *document, const QString &filter = QString(),
|
||||||
QString *selectedFilter = 0);
|
QString *selectedFilter = 0);
|
||||||
|
|
||||||
static QList<IDocument *> saveModifiedDocumentsSilently(const QList<IDocument *> &documents, bool *cancelled = 0);
|
static QList<IDocument *> saveModifiedDocumentsSilently(const QList<IDocument *> &documents, bool *cancelled = 0);
|
||||||
@@ -108,15 +107,6 @@ public:
|
|||||||
const QString &alwaysSaveMessage = QString(),
|
const QString &alwaysSaveMessage = QString(),
|
||||||
bool *alwaysSave = 0);
|
bool *alwaysSave = 0);
|
||||||
|
|
||||||
|
|
||||||
// Helper to display a message dialog when encountering a read-only
|
|
||||||
// file, prompting the user about how to make it writeable.
|
|
||||||
enum ReadOnlyAction { RO_Cancel, RO_OpenVCS, RO_MakeWriteable, RO_SaveAs };
|
|
||||||
static ReadOnlyAction promptReadOnlyFile(const QString &fileName,
|
|
||||||
const IVersionControl *versionControl,
|
|
||||||
QWidget *parent,
|
|
||||||
bool displaySaveAsButton = false);
|
|
||||||
|
|
||||||
static QString fileDialogLastVisitedDirectory();
|
static QString fileDialogLastVisitedDirectory();
|
||||||
static void setFileDialogLastVisitedDirectory(const QString &);
|
static void setFileDialogLastVisitedDirectory(const QString &);
|
||||||
|
|
||||||
|
@@ -52,6 +52,7 @@
|
|||||||
#include <coreplugin/modemanager.h>
|
#include <coreplugin/modemanager.h>
|
||||||
#include <coreplugin/settingsdatabase.h>
|
#include <coreplugin/settingsdatabase.h>
|
||||||
#include <coreplugin/variablemanager.h>
|
#include <coreplugin/variablemanager.h>
|
||||||
|
#include <coreplugin/dialogs/readonlyfilesdialog.h>
|
||||||
|
|
||||||
#include <extensionsystem/pluginmanager.h>
|
#include <extensionsystem/pluginmanager.h>
|
||||||
|
|
||||||
@@ -1578,34 +1579,18 @@ MakeWritableResult EditorManager::makeFileWritable(IDocument *document)
|
|||||||
{
|
{
|
||||||
if (!document)
|
if (!document)
|
||||||
return Failed;
|
return Failed;
|
||||||
QString directory = QFileInfo(document->fileName()).absolutePath();
|
|
||||||
IVersionControl *versionControl = ICore::vcsManager()->findVersionControlForDirectory(directory);
|
|
||||||
const QString &fileName = document->fileName();
|
|
||||||
|
|
||||||
switch (DocumentManager::promptReadOnlyFile(fileName, versionControl, ICore::mainWindow(), document->isSaveAsAllowed())) {
|
ReadOnlyFilesDialog roDialog(document, ICore::mainWindow(), document->isSaveAsAllowed());
|
||||||
case DocumentManager::RO_OpenVCS:
|
switch (roDialog.exec()) {
|
||||||
if (!versionControl->vcsOpen(fileName)) {
|
case ReadOnlyFilesDialog::RO_MakeWritable:
|
||||||
QMessageBox::warning(ICore::mainWindow(), tr("Cannot Open File"), tr("Cannot open the file for editing with SCC."));
|
case ReadOnlyFilesDialog::RO_OpenVCS:
|
||||||
return Failed;
|
|
||||||
}
|
|
||||||
document->checkPermissions();
|
|
||||||
return OpenedWithVersionControl;
|
|
||||||
case DocumentManager::RO_MakeWriteable: {
|
|
||||||
const bool permsOk = QFile::setPermissions(fileName, QFile::permissions(fileName) | QFile::WriteUser);
|
|
||||||
if (!permsOk) {
|
|
||||||
QMessageBox::warning(ICore::mainWindow(), tr("Cannot Set Permissions"), tr("Cannot set permissions to writable."));
|
|
||||||
return Failed;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
document->checkPermissions();
|
|
||||||
return MadeWritable;
|
return MadeWritable;
|
||||||
case DocumentManager::RO_SaveAs :
|
case ReadOnlyFilesDialog::RO_SaveAs:
|
||||||
return saveDocumentAs(document) ? SavedAs : Failed;
|
return SavedAs;
|
||||||
case DocumentManager::RO_Cancel:
|
default:
|
||||||
break;
|
|
||||||
}
|
|
||||||
return Failed;
|
return Failed;
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
bool EditorManager::saveDocumentAs(IDocument *documentParam)
|
bool EditorManager::saveDocumentAs(IDocument *documentParam)
|
||||||
{
|
{
|
||||||
|
@@ -163,7 +163,7 @@ QString PerforceVersionControl::vcsGetRepositoryURL(const QString &)
|
|||||||
|
|
||||||
QString PerforceVersionControl::vcsOpenText() const
|
QString PerforceVersionControl::vcsOpenText() const
|
||||||
{
|
{
|
||||||
return tr("&Edit (%1)").arg(displayName());
|
return tr("&Edit");
|
||||||
}
|
}
|
||||||
|
|
||||||
QString PerforceVersionControl::vcsMakeWritableText() const
|
QString PerforceVersionControl::vcsMakeWritableText() const
|
||||||
|
@@ -43,6 +43,7 @@
|
|||||||
#include <coreplugin/icore.h>
|
#include <coreplugin/icore.h>
|
||||||
#include <coreplugin/iversioncontrol.h>
|
#include <coreplugin/iversioncontrol.h>
|
||||||
#include <coreplugin/vcsmanager.h>
|
#include <coreplugin/vcsmanager.h>
|
||||||
|
#include <coreplugin/dialogs/readonlyfilesdialog.h>
|
||||||
|
|
||||||
#include <projectexplorer/buildmanager.h>
|
#include <projectexplorer/buildmanager.h>
|
||||||
#include <projectexplorer/projectexplorer.h>
|
#include <projectexplorer/projectexplorer.h>
|
||||||
@@ -1023,28 +1024,9 @@ bool Qt4PriFileNode::renameFile(const FileType fileType, const QString &filePath
|
|||||||
|
|
||||||
bool Qt4PriFileNode::priFileWritable(const QString &path)
|
bool Qt4PriFileNode::priFileWritable(const QString &path)
|
||||||
{
|
{
|
||||||
const QString dir = QFileInfo(path).dir().path();
|
Core::Internal::ReadOnlyFilesDialog roDialog(path, Core::ICore::mainWindow());
|
||||||
Core::IVersionControl *versionControl = Core::ICore::vcsManager()->findVersionControlForDirectory(dir);
|
roDialog.setShowFailWarning(true);
|
||||||
switch (Core::DocumentManager::promptReadOnlyFile(path, versionControl, Core::ICore::mainWindow(), false)) {
|
return roDialog.exec() != Core::Internal::ReadOnlyFilesDialog::RO_Cancel;
|
||||||
case Core::DocumentManager::RO_OpenVCS:
|
|
||||||
if (!versionControl->vcsOpen(path)) {
|
|
||||||
QMessageBox::warning(Core::ICore::mainWindow(), tr("Cannot Open File"), tr("Cannot open the file for editing with VCS."));
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
case Core::DocumentManager::RO_MakeWriteable: {
|
|
||||||
const bool permsOk = QFile::setPermissions(path, QFile::permissions(path) | QFile::WriteUser);
|
|
||||||
if (!permsOk) {
|
|
||||||
QMessageBox::warning(Core::ICore::mainWindow(), tr("Cannot Set Permissions"), tr("Cannot set permissions to writable."));
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
case Core::DocumentManager::RO_SaveAs:
|
|
||||||
case Core::DocumentManager::RO_Cancel:
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
return true;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
bool Qt4PriFileNode::saveModifiedEditors()
|
bool Qt4PriFileNode::saveModifiedEditors()
|
||||||
|
@@ -34,6 +34,7 @@
|
|||||||
#include <coreplugin/icore.h>
|
#include <coreplugin/icore.h>
|
||||||
#include <coreplugin/progressmanager/progressmanager.h>
|
#include <coreplugin/progressmanager/progressmanager.h>
|
||||||
#include <coreplugin/progressmanager/futureprogress.h>
|
#include <coreplugin/progressmanager/futureprogress.h>
|
||||||
|
#include <coreplugin/dialogs/readonlyfilesdialog.h>
|
||||||
#include <coreplugin/documentmanager.h>
|
#include <coreplugin/documentmanager.h>
|
||||||
#include <texteditor/basetexteditor.h>
|
#include <texteditor/basetexteditor.h>
|
||||||
#include <texteditor/refactoringchanges.h>
|
#include <texteditor/refactoringchanges.h>
|
||||||
@@ -363,7 +364,26 @@ QStringList BaseFileFind::replaceAll(const QString &text,
|
|||||||
foreach (const Find::SearchResultItem &item, items)
|
foreach (const Find::SearchResultItem &item, items)
|
||||||
changes[QDir::fromNativeSeparators(item.path.first())].append(item);
|
changes[QDir::fromNativeSeparators(item.path.first())].append(item);
|
||||||
|
|
||||||
|
// Checking for files without write permissions
|
||||||
QHashIterator<QString, QList<Find::SearchResultItem> > it(changes);
|
QHashIterator<QString, QList<Find::SearchResultItem> > it(changes);
|
||||||
|
QSet<QString> roFiles;
|
||||||
|
while (it.hasNext()) {
|
||||||
|
it.next();
|
||||||
|
const QFileInfo fileInfo(it.key());
|
||||||
|
if (!fileInfo.isWritable())
|
||||||
|
roFiles.insert(it.key());
|
||||||
|
}
|
||||||
|
|
||||||
|
// Query the user for permissions
|
||||||
|
if (!roFiles.isEmpty()) {
|
||||||
|
Core::Internal::ReadOnlyFilesDialog roDialog(roFiles.toList(),
|
||||||
|
Core::ICore::instance()->mainWindow());
|
||||||
|
roDialog.setShowFailWarning(true, tr("Aborting replace."));
|
||||||
|
if (roDialog.exec() == Core::Internal::ReadOnlyFilesDialog::RO_Cancel)
|
||||||
|
return QStringList();
|
||||||
|
}
|
||||||
|
|
||||||
|
it.toFront();
|
||||||
while (it.hasNext()) {
|
while (it.hasNext()) {
|
||||||
it.next();
|
it.next();
|
||||||
const QString fileName = it.key();
|
const QString fileName = it.key();
|
||||||
|
@@ -30,13 +30,18 @@
|
|||||||
#include "refactoringchanges.h"
|
#include "refactoringchanges.h"
|
||||||
#include "basetexteditor.h"
|
#include "basetexteditor.h"
|
||||||
|
|
||||||
|
#include <coreplugin/icore.h>
|
||||||
|
#include <coreplugin/dialogs/readonlyfilesdialog.h>
|
||||||
#include <utils/qtcassert.h>
|
#include <utils/qtcassert.h>
|
||||||
|
#include <utils/fileutils.h>
|
||||||
|
|
||||||
#include <QFile>
|
#include <QFile>
|
||||||
|
#include <QFileInfo>
|
||||||
#include <QTextBlock>
|
#include <QTextBlock>
|
||||||
#include <QTextCursor>
|
#include <QTextCursor>
|
||||||
#include <QTextDocument>
|
#include <QTextDocument>
|
||||||
#include <QDebug>
|
#include <QDebug>
|
||||||
|
#include <QApplication>
|
||||||
|
|
||||||
using namespace TextEditor;
|
using namespace TextEditor;
|
||||||
|
|
||||||
@@ -319,6 +324,17 @@ void RefactoringFile::setOpenEditor(bool activate, int pos)
|
|||||||
|
|
||||||
void RefactoringFile::apply()
|
void RefactoringFile::apply()
|
||||||
{
|
{
|
||||||
|
// test file permissions
|
||||||
|
if (!QFileInfo(fileName()).isWritable()) {
|
||||||
|
const QString &path = fileName();
|
||||||
|
Core::Internal::ReadOnlyFilesDialog roDialog(path, Core::ICore::mainWindow());
|
||||||
|
const QString &failDetailText = QApplication::translate("RefactoringFile::apply",
|
||||||
|
"Refactoring cannot be applied.");
|
||||||
|
roDialog.setShowFailWarning(true, failDetailText);
|
||||||
|
if (roDialog.exec() == Core::Internal::ReadOnlyFilesDialog::RO_Cancel)
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
// open / activate / goto position
|
// open / activate / goto position
|
||||||
if (m_openEditor && !m_fileName.isEmpty()) {
|
if (m_openEditor && !m_fileName.isEmpty()) {
|
||||||
unsigned line = unsigned(-1), column = unsigned(-1);
|
unsigned line = unsigned(-1), column = unsigned(-1);
|
||||||
|
Reference in New Issue
Block a user