forked from qt-creator/qt-creator
Allow pinning files to ensure that they are always open
This patch allows pinning files within a session. Pinning a file puts it at the top of the Open Documents list, and prevents Close All from closing it until it is unpinned. This is useful for files that should always be open for a given session. [ChangeLog] Files can now be pinned via the context menu. Pinning a file keeps it at the top of the Open Documents list, and prevents Close All and similar actions from closing it until it is unpinned. This provides a way to quickly close any open files without closing important ones. Change-Id: If47a599fb272db4c78a71eabe6fb29215a9a8a11 Fixes: QTCREATORBUG-21899 Reviewed-by: Eike Ziller <eike.ziller@qt.io>
This commit is contained in:
@@ -194,6 +194,20 @@
|
||||
|
||||
//! [projects view]
|
||||
|
||||
//! [open documents view]
|
||||
|
||||
\section2 Viewing Open Documents
|
||||
|
||||
To see a list of open documents, switch to the \uicontrol {Open Documents}
|
||||
view. By right-clicking an open document, you can:
|
||||
|
||||
\list
|
||||
\li Pin files to ensure they stay at the top of the list and are not
|
||||
closed when \uicontrol {Close All} is used.
|
||||
\endlist
|
||||
|
||||
//! [open documents view]
|
||||
|
||||
//! [file system view]
|
||||
|
||||
\section2 Viewing the File System
|
||||
|
||||
@@ -148,6 +148,7 @@
|
||||
|
||||
\include creator-sidebar-views.qdocinc using sidebar views
|
||||
\include creator-sidebar-views.qdocinc projects view
|
||||
\include creator-sidebar-views.qdocinc open documents view
|
||||
\include creator-sidebar-views.qdocinc file system view
|
||||
\include creator-sidebar-views.qdocinc outline view
|
||||
\if defined(qtcreator)
|
||||
|
||||
BIN
src/libs/utils/images/pinned.png
Normal file
BIN
src/libs/utils/images/pinned.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 168 B |
BIN
src/libs/utils/images/pinned@2x.png
Normal file
BIN
src/libs/utils/images/pinned@2x.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 267 B |
@@ -34,6 +34,8 @@
|
||||
<file>images/locked@2x.png</file>
|
||||
<file>images/unlocked.png</file>
|
||||
<file>images/unlocked@2x.png</file>
|
||||
<file>images/pinned.png</file>
|
||||
<file>images/pinned@2x.png</file>
|
||||
<file>images/broken.png</file>
|
||||
<file>images/broken@2x.png</file>
|
||||
<file>images/notloaded.png</file>
|
||||
|
||||
@@ -43,6 +43,8 @@ const Icon LOCKED({
|
||||
{QLatin1String(":/utils/images/locked.png"), Theme::PanelTextColorDark}}, Icon::Tint);
|
||||
const Icon UNLOCKED_TOOLBAR({
|
||||
{QLatin1String(":/utils/images/unlocked.png"), Theme::IconsBaseColor}});
|
||||
const Icon PINNED({
|
||||
{QLatin1String(":/utils/images/pinned.png"), Theme::PanelTextColorDark}}, Icon::Tint);
|
||||
const Icon NEXT({
|
||||
{QLatin1String(":/utils/images/next.png"), Theme::IconsWarningColor}}, Icon::MenuTintedStyle);
|
||||
const Icon NEXT_TOOLBAR({
|
||||
|
||||
@@ -38,6 +38,7 @@ QTCREATOR_UTILS_EXPORT extern const Icon EDIT_CLEAR_TOOLBAR;
|
||||
QTCREATOR_UTILS_EXPORT extern const Icon LOCKED_TOOLBAR;
|
||||
QTCREATOR_UTILS_EXPORT extern const Icon LOCKED;
|
||||
QTCREATOR_UTILS_EXPORT extern const Icon UNLOCKED_TOOLBAR;
|
||||
QTCREATOR_UTILS_EXPORT extern const Icon PINNED;
|
||||
QTCREATOR_UTILS_EXPORT extern const Icon NEXT;
|
||||
QTCREATOR_UTILS_EXPORT extern const Icon NEXT_TOOLBAR;
|
||||
QTCREATOR_UTILS_EXPORT extern const Icon PREV;
|
||||
|
||||
@@ -43,7 +43,6 @@
|
||||
#include <QSet>
|
||||
#include <QUrl>
|
||||
|
||||
|
||||
static Core::Internal::DocumentModelPrivate *d;
|
||||
|
||||
namespace Core {
|
||||
@@ -52,6 +51,10 @@ namespace Internal {
|
||||
namespace {
|
||||
bool compare(const DocumentModel::Entry *e1, const DocumentModel::Entry *e2)
|
||||
{
|
||||
// Pinned files should go at the top.
|
||||
if (e1->pinned != e2->pinned)
|
||||
return e1->pinned;
|
||||
|
||||
const int cmp = e1->plainDisplayName().localeAwareCompare(e2->plainDisplayName());
|
||||
return (cmp < 0) || (cmp == 0 && e1->fileName() < e2->fileName());
|
||||
}
|
||||
@@ -111,7 +114,8 @@ void DocumentModelPrivate::addEntry(DocumentModel::Entry *entry)
|
||||
previousEntry->isSuspended = false;
|
||||
delete previousEntry->document;
|
||||
previousEntry->document = entry->document;
|
||||
connect(previousEntry->document, &IDocument::changed, this, &DocumentModelPrivate::itemChanged);
|
||||
connect(previousEntry->document, &IDocument::changed,
|
||||
this, [this, document = previousEntry->document] { itemChanged(document); });
|
||||
}
|
||||
delete entry;
|
||||
entry = nullptr;
|
||||
@@ -129,7 +133,9 @@ void DocumentModelPrivate::addEntry(DocumentModel::Entry *entry)
|
||||
disambiguateDisplayNames(entry);
|
||||
if (!fixedPath.isEmpty())
|
||||
m_entryByFixedPath[fixedPath] = entry;
|
||||
connect(entry->document, &IDocument::changed, this, &DocumentModelPrivate::itemChanged);
|
||||
connect(entry->document, &IDocument::changed, this, [this, document = entry->document] {
|
||||
itemChanged(document);
|
||||
});
|
||||
endInsertRows();
|
||||
}
|
||||
|
||||
@@ -196,12 +202,29 @@ bool DocumentModelPrivate::disambiguateDisplayNames(DocumentModel::Entry *entry)
|
||||
return true;
|
||||
}
|
||||
|
||||
void DocumentModelPrivate::setPinned(DocumentModel::Entry *entry, bool pinned)
|
||||
{
|
||||
if (entry->pinned == pinned)
|
||||
return;
|
||||
|
||||
entry->pinned = pinned;
|
||||
// Ensure that this entry is re-sorted in the list of open documents
|
||||
// now that its pinned state has changed.
|
||||
d->itemChanged(entry->document);
|
||||
}
|
||||
|
||||
QIcon DocumentModelPrivate::lockedIcon()
|
||||
{
|
||||
const static QIcon icon = Utils::Icons::LOCKED.icon();
|
||||
return icon;
|
||||
}
|
||||
|
||||
QIcon DocumentModelPrivate::pinnedIcon()
|
||||
{
|
||||
const static QIcon icon = Utils::Icons::PINNED.icon();
|
||||
return icon;
|
||||
}
|
||||
|
||||
Utils::optional<int> DocumentModelPrivate::indexOfFilePath(const Utils::FileName &filePath) const
|
||||
{
|
||||
if (filePath.isEmpty())
|
||||
@@ -230,7 +253,7 @@ void DocumentModelPrivate::removeDocument(int idx)
|
||||
DocumentManager::ResolveLinks);
|
||||
m_entryByFixedPath.remove(fixedPath);
|
||||
}
|
||||
disconnect(entry->document, &IDocument::changed, this, &DocumentModelPrivate::itemChanged);
|
||||
disconnect(entry->document, &IDocument::changed, this, nullptr);
|
||||
disambiguateDisplayNames(entry);
|
||||
delete entry;
|
||||
}
|
||||
@@ -307,7 +330,11 @@ QVariant DocumentModelPrivate::data(const QModelIndex &index, int role) const
|
||||
return name;
|
||||
}
|
||||
case Qt::DecorationRole:
|
||||
return entry->document->isFileReadOnly() ? lockedIcon() : QIcon();
|
||||
if (entry->document->isFileReadOnly())
|
||||
return lockedIcon();
|
||||
if (entry->pinned)
|
||||
return pinnedIcon();
|
||||
return QIcon();
|
||||
case Qt::ToolTipRole:
|
||||
return entry->fileName().isEmpty() ? entry->displayName() : entry->fileName().toUserOutput();
|
||||
default:
|
||||
@@ -316,10 +343,8 @@ QVariant DocumentModelPrivate::data(const QModelIndex &index, int role) const
|
||||
return QVariant();
|
||||
}
|
||||
|
||||
void DocumentModelPrivate::itemChanged()
|
||||
void DocumentModelPrivate::itemChanged(IDocument *document)
|
||||
{
|
||||
auto document = qobject_cast<IDocument *>(sender());
|
||||
|
||||
const Utils::optional<int> idx = indexOfDocument(document);
|
||||
if (!idx)
|
||||
return;
|
||||
@@ -353,14 +378,19 @@ void DocumentModelPrivate::itemChanged()
|
||||
// Make sure the entries stay sorted:
|
||||
auto positions = positionEntry(m_entries, entry);
|
||||
if (positions.first >= 0 && positions.second >= 0) {
|
||||
// Entry did move: remove and add it again.
|
||||
beginRemoveRows(QModelIndex(), positions.first + 1, positions.first + 1);
|
||||
m_entries.removeAt(positions.first);
|
||||
endRemoveRows();
|
||||
// Entry did move: update its position.
|
||||
|
||||
beginInsertRows(QModelIndex(), positions.second + 1, positions.second + 1);
|
||||
m_entries.insert(positions.second, entry);
|
||||
endInsertRows();
|
||||
// Account for the <no document> entry.
|
||||
static const int noDocumentEntryOffset = 1;
|
||||
const int fromIndex = positions.first + noDocumentEntryOffset;
|
||||
const int toIndex = positions.second + noDocumentEntryOffset;
|
||||
// Account for the weird requirements of beginMoveRows().
|
||||
const int effectiveToIndex = toIndex > fromIndex ? toIndex + 1 : toIndex;
|
||||
beginMoveRows(QModelIndex(), fromIndex, fromIndex, QModelIndex(), effectiveToIndex);
|
||||
|
||||
m_entries.move(fromIndex - 1, toIndex - 1);
|
||||
|
||||
endMoveRows();
|
||||
} else {
|
||||
// Nothing to remove or add: The entry did not move.
|
||||
QTC_CHECK(positions.first == -1 && positions.second == -1);
|
||||
@@ -384,7 +414,9 @@ void DocumentModelPrivate::addEditor(IEditor *editor, bool *isNewDocument)
|
||||
}
|
||||
}
|
||||
|
||||
void DocumentModelPrivate::addSuspendedDocument(const QString &fileName, const QString &displayName, Id id)
|
||||
DocumentModel::Entry *DocumentModelPrivate::addSuspendedDocument(const QString &fileName,
|
||||
const QString &displayName,
|
||||
Id id)
|
||||
{
|
||||
auto entry = new DocumentModel::Entry;
|
||||
entry->document = new IDocument;
|
||||
@@ -393,6 +425,7 @@ void DocumentModelPrivate::addSuspendedDocument(const QString &fileName, const Q
|
||||
entry->document->setId(id);
|
||||
entry->isSuspended = true;
|
||||
d->addEntry(entry);
|
||||
return entry;
|
||||
}
|
||||
|
||||
DocumentModel::Entry *DocumentModelPrivate::firstSuspendedEntry()
|
||||
@@ -433,15 +466,20 @@ void DocumentModelPrivate::removeEntry(DocumentModel::Entry *entry)
|
||||
d->removeDocument(index);
|
||||
}
|
||||
|
||||
void DocumentModelPrivate::removeAllSuspendedEntries()
|
||||
void DocumentModelPrivate::removeAllSuspendedEntries(PinnedFileRemovalPolicy pinnedFileRemovalPolicy)
|
||||
{
|
||||
for (int i = d->m_entries.count()-1; i >= 0; --i) {
|
||||
if (d->m_entries.at(i)->isSuspended) {
|
||||
int row = i + 1/*<no document>*/;
|
||||
d->beginRemoveRows(QModelIndex(), row, row);
|
||||
delete d->m_entries.takeAt(i);
|
||||
d->endRemoveRows();
|
||||
}
|
||||
const DocumentModel::Entry *entry = d->m_entries.at(i);
|
||||
if (!entry->isSuspended)
|
||||
continue;
|
||||
|
||||
if (pinnedFileRemovalPolicy == DoNotRemovePinnedFiles && entry->pinned)
|
||||
continue;
|
||||
|
||||
int row = i + 1/*<no document>*/;
|
||||
d->beginRemoveRows(QModelIndex(), row, row);
|
||||
delete d->m_entries.takeAt(i);
|
||||
d->endRemoveRows();
|
||||
}
|
||||
QSet<QString> displayNames;
|
||||
foreach (DocumentModel::Entry *entry, d->m_entries) {
|
||||
@@ -480,7 +518,8 @@ void DocumentModelPrivate::DynamicEntry::setNumberedName(int number)
|
||||
|
||||
DocumentModel::Entry::Entry() :
|
||||
document(nullptr),
|
||||
isSuspended(false)
|
||||
isSuspended(false),
|
||||
pinned(false)
|
||||
{
|
||||
}
|
||||
|
||||
|
||||
@@ -60,7 +60,17 @@ public:
|
||||
Id id() const;
|
||||
|
||||
IDocument *document;
|
||||
// When an entry is suspended, it means that it is not in memory,
|
||||
// and there is no IEditor for it and only a dummy IDocument.
|
||||
// This is typically the case for files that have not been opened yet,
|
||||
// but can also happen later after they have been opened.
|
||||
// The related setting for this is found in:
|
||||
// Options > Environment > System > Auto-suspend unmodified files
|
||||
bool isSuspended;
|
||||
// The entry has been pinned, which means that it should stick to
|
||||
// the top of any lists of open files, and that any actions that close
|
||||
// files in bulk should not close this one.
|
||||
bool pinned;
|
||||
};
|
||||
|
||||
static Entry *entryAtRow(int row);
|
||||
|
||||
@@ -63,15 +63,25 @@ public:
|
||||
|
||||
bool disambiguateDisplayNames(DocumentModel::Entry *entry);
|
||||
|
||||
static void setPinned(DocumentModel::Entry *entry, bool pinned);
|
||||
|
||||
static QIcon lockedIcon();
|
||||
static QIcon pinnedIcon();
|
||||
static void addEditor(IEditor *editor, bool *isNewDocument);
|
||||
static void addSuspendedDocument(const QString &fileName, const QString &displayName, Id id);
|
||||
static DocumentModel::Entry *addSuspendedDocument(const QString &fileName,
|
||||
const QString &displayName,
|
||||
Id id);
|
||||
static DocumentModel::Entry *firstSuspendedEntry();
|
||||
static DocumentModel::Entry *removeEditor(IEditor *editor);
|
||||
static void removeEntry(DocumentModel::Entry *entry);
|
||||
static void removeAllSuspendedEntries();
|
||||
enum PinnedFileRemovalPolicy {
|
||||
DoNotRemovePinnedFiles,
|
||||
RemovePinnedFiles
|
||||
};
|
||||
static void removeAllSuspendedEntries(PinnedFileRemovalPolicy pinnedFileRemovalPolicy
|
||||
= RemovePinnedFiles);
|
||||
|
||||
void itemChanged();
|
||||
void itemChanged(IDocument *document);
|
||||
|
||||
class DynamicEntry
|
||||
{
|
||||
|
||||
@@ -216,7 +216,8 @@ EditorManagerPrivate::EditorManagerPrivate(QObject *parent) :
|
||||
m_openGraphicalShellAction(new QAction(FileUtils::msgGraphicalShellAction(), this)),
|
||||
m_openTerminalAction(new QAction(FileUtils::msgTerminalAction(), this)),
|
||||
m_findInDirectoryAction(new QAction(FileUtils::msgFindInDirectory(), this)),
|
||||
m_filePropertiesAction(new QAction(tr("Properties..."), this))
|
||||
m_filePropertiesAction(new QAction(tr("Properties..."), this)),
|
||||
m_pinAction(new QAction(tr("Pin"), this))
|
||||
{
|
||||
d = this;
|
||||
}
|
||||
@@ -302,8 +303,7 @@ void EditorManagerPrivate::init()
|
||||
cmd = ActionManager::registerAction(m_closeAllEditorsAction, Constants::CLOSEALL, editManagerContext, true);
|
||||
cmd->setDefaultKeySequence(QKeySequence(tr("Ctrl+Shift+W")));
|
||||
mfile->addAction(cmd, Constants::G_FILE_CLOSE);
|
||||
connect(m_closeAllEditorsAction, &QAction::triggered,
|
||||
m_instance, []() { EditorManager::closeAllEditors(); });
|
||||
connect(m_closeAllEditorsAction, &QAction::triggered, m_instance, &EditorManager::closeAllDocuments);
|
||||
|
||||
// Close All Others Action
|
||||
cmd = ActionManager::registerAction(m_closeOtherDocumentsAction, Constants::CLOSEOTHERS, editManagerContext, true);
|
||||
@@ -334,7 +334,7 @@ void EditorManagerPrivate::init()
|
||||
|
||||
// Close XXX Context Actions
|
||||
connect(m_closeAllEditorsContextAction, &QAction::triggered,
|
||||
m_instance, []() { EditorManager::closeAllEditors(); });
|
||||
m_instance, &EditorManager::closeAllDocuments);
|
||||
connect(m_closeCurrentEditorContextAction, &QAction::triggered,
|
||||
this, &EditorManagerPrivate::closeEditorFromContextMenu);
|
||||
connect(m_closeOtherDocumentsContextAction, &QAction::triggered,
|
||||
@@ -352,6 +352,7 @@ void EditorManagerPrivate::init()
|
||||
return;
|
||||
DocumentManager::showFilePropertiesDialog(d->m_contextMenuEntry->fileName());
|
||||
});
|
||||
connect(m_pinAction, &QAction::triggered, this, &EditorManagerPrivate::togglePinned);
|
||||
|
||||
// Goto Previous In History Action
|
||||
cmd = ActionManager::registerAction(m_gotoPreviousDocHistoryAction, Constants::GOTOPREVINHISTORY, editDesignContext);
|
||||
@@ -2217,8 +2218,13 @@ bool EditorManagerPrivate::saveDocumentAs(IDocument *document)
|
||||
|
||||
void EditorManagerPrivate::closeAllEditorsExceptVisible()
|
||||
{
|
||||
DocumentModelPrivate::removeAllSuspendedEntries();
|
||||
DocumentModelPrivate::removeAllSuspendedEntries(DocumentModelPrivate::DoNotRemovePinnedFiles);
|
||||
QList<IDocument *> documentsToClose = DocumentModel::openedDocuments();
|
||||
// Remove all pinned files from the list of files to close.
|
||||
documentsToClose = Utils::filtered(documentsToClose, [](IDocument *document) {
|
||||
DocumentModel::Entry *entry = DocumentModel::entryForDocument(document);
|
||||
return !entry->pinned;
|
||||
});
|
||||
foreach (IEditor *editor, EditorManager::visibleEditors())
|
||||
documentsToClose.removeAll(editor->document());
|
||||
EditorManager::closeDocuments(documentsToClose, true);
|
||||
@@ -2303,6 +2309,15 @@ void EditorManagerPrivate::findInDirectory()
|
||||
emit m_instance->findOnFileSystemRequest(d->m_contextMenuEntry->fileName().parentDir().toString());
|
||||
}
|
||||
|
||||
void EditorManagerPrivate::togglePinned()
|
||||
{
|
||||
if (!d->m_contextMenuEntry || d->m_contextMenuEntry->fileName().isEmpty())
|
||||
return;
|
||||
|
||||
const bool currentlyPinned = d->m_contextMenuEntry->pinned;
|
||||
DocumentModelPrivate::setPinned(d->m_contextMenuEntry, !currentlyPinned);
|
||||
}
|
||||
|
||||
void EditorManagerPrivate::split(Qt::Orientation orientation)
|
||||
{
|
||||
EditorView *view = currentEditorView();
|
||||
@@ -2401,12 +2416,25 @@ bool EditorManager::closeAllEditors(bool askAboutModifiedEditors)
|
||||
|
||||
void EditorManager::closeOtherDocuments(IDocument *document)
|
||||
{
|
||||
DocumentModelPrivate::removeAllSuspendedEntries();
|
||||
DocumentModelPrivate::removeAllSuspendedEntries(DocumentModelPrivate::DoNotRemovePinnedFiles);
|
||||
QList<IDocument *> documentsToClose = DocumentModel::openedDocuments();
|
||||
// Remove all pinned files from the list of files to close.
|
||||
documentsToClose = Utils::filtered(documentsToClose, [](IDocument *document) {
|
||||
DocumentModel::Entry *entry = DocumentModel::entryForDocument(document);
|
||||
return !entry->pinned;
|
||||
});
|
||||
documentsToClose.removeAll(document);
|
||||
closeDocuments(documentsToClose, true);
|
||||
}
|
||||
|
||||
void EditorManager::closeAllDocuments()
|
||||
{
|
||||
// Only close the files that aren't pinned.
|
||||
const QList<DocumentModel::Entry *> entriesToClose
|
||||
= Utils::filtered(DocumentModel::entries(), Utils::equal(&DocumentModel::Entry::pinned, false));
|
||||
EditorManager::closeDocuments(entriesToClose);
|
||||
}
|
||||
|
||||
// SLOT connected to action
|
||||
void EditorManager::slotCloseCurrentEditorOrDocument()
|
||||
{
|
||||
@@ -2488,6 +2516,20 @@ void EditorManager::addSaveAndCloseEditorActions(QMenu *contextMenu, DocumentMod
|
||||
contextMenu->addAction(d->m_closeAllEditorsExceptVisibleContextAction);
|
||||
}
|
||||
|
||||
void EditorManager::addPinEditorActions(QMenu *contextMenu, DocumentModel::Entry *entry)
|
||||
{
|
||||
const QString quotedDisplayName = entry ? Utils::quoteAmpersands(entry->displayName()) : QString();
|
||||
if (entry) {
|
||||
d->m_pinAction->setText(entry->pinned
|
||||
? tr("Unpin \"%1\"").arg(quotedDisplayName)
|
||||
: tr("Pin \"%1\"").arg(quotedDisplayName));
|
||||
} else {
|
||||
d->m_pinAction->setText(tr("Pin Editor"));
|
||||
}
|
||||
d->m_pinAction->setEnabled(entry != nullptr);
|
||||
contextMenu->addAction(d->m_pinAction);
|
||||
}
|
||||
|
||||
void EditorManager::addNativeDirAndOpenWithActions(QMenu *contextMenu, DocumentModel::Entry *entry)
|
||||
{
|
||||
QTC_ASSERT(contextMenu, return);
|
||||
@@ -2587,6 +2629,20 @@ void EditorManager::closeDocument(DocumentModel::Entry *entry)
|
||||
closeDocuments({entry->document});
|
||||
}
|
||||
|
||||
void EditorManager::closeDocuments(const QList<DocumentModel::Entry *> &entries)
|
||||
{
|
||||
QList<IDocument *> documentsToClose;
|
||||
for (DocumentModel::Entry *entry : entries) {
|
||||
if (!entry)
|
||||
continue;
|
||||
if (entry->isSuspended)
|
||||
DocumentModelPrivate::removeEntry(entry);
|
||||
else
|
||||
documentsToClose << entry->document;
|
||||
}
|
||||
closeDocuments(documentsToClose);
|
||||
}
|
||||
|
||||
bool EditorManager::closeEditors(const QList<IEditor*> &editorsToClose, bool askAboutModifiedEditors)
|
||||
{
|
||||
return EditorManagerPrivate::closeEditors(editorsToClose,
|
||||
@@ -2906,13 +2962,13 @@ QVector<EditorWindow *> editorWindows(const QList<EditorArea *> &areas)
|
||||
return result;
|
||||
}
|
||||
|
||||
// Save state of all non-teporary editors.
|
||||
// Save state of all non-temporary editors.
|
||||
QByteArray EditorManager::saveState()
|
||||
{
|
||||
QByteArray bytes;
|
||||
QDataStream stream(&bytes, QIODevice::WriteOnly);
|
||||
|
||||
stream << QByteArray("EditorManagerV4");
|
||||
stream << QByteArray("EditorManagerV5");
|
||||
|
||||
// TODO: In case of split views it's not possible to restore these for all correctly with this
|
||||
QList<IDocument *> documents = DocumentModel::openedDocuments();
|
||||
@@ -2938,8 +2994,10 @@ QByteArray EditorManager::saveState()
|
||||
stream << entriesCount;
|
||||
|
||||
foreach (DocumentModel::Entry *entry, entries) {
|
||||
if (!entry->document->isTemporary())
|
||||
stream << entry->fileName().toString() << entry->plainDisplayName() << entry->id();
|
||||
if (!entry->document->isTemporary()) {
|
||||
stream << entry->fileName().toString() << entry->plainDisplayName() << entry->id()
|
||||
<< entry->pinned;
|
||||
}
|
||||
}
|
||||
|
||||
stream << d->m_editorAreas.first()->saveState(); // TODO
|
||||
@@ -2964,7 +3022,8 @@ bool EditorManager::restoreState(const QByteArray &state)
|
||||
QByteArray version;
|
||||
stream >> version;
|
||||
|
||||
if (version != "EditorManagerV4")
|
||||
const bool isVersion5 = version == "EditorManagerV5";
|
||||
if (version != "EditorManagerV4" && !isVersion5)
|
||||
return false;
|
||||
|
||||
QApplication::setOverrideCursor(Qt::WaitCursor);
|
||||
@@ -2980,16 +3039,22 @@ bool EditorManager::restoreState(const QByteArray &state)
|
||||
stream >> displayName;
|
||||
Id id;
|
||||
stream >> id;
|
||||
bool pinned = false;
|
||||
if (isVersion5)
|
||||
stream >> pinned;
|
||||
|
||||
if (!fileName.isEmpty() && !displayName.isEmpty()) {
|
||||
QFileInfo fi(fileName);
|
||||
if (!fi.exists())
|
||||
continue;
|
||||
QFileInfo rfi(autoSaveName(fileName));
|
||||
if (rfi.exists() && fi.lastModified() < rfi.lastModified())
|
||||
openEditor(fileName, id, DoNotMakeVisible);
|
||||
else
|
||||
DocumentModelPrivate::addSuspendedDocument(fileName, displayName, id);
|
||||
if (rfi.exists() && fi.lastModified() < rfi.lastModified()) {
|
||||
if (IEditor *editor = openEditor(fileName, id, DoNotMakeVisible))
|
||||
DocumentModelPrivate::setPinned(DocumentModel::entryForDocument(editor->document()), pinned);
|
||||
} else {
|
||||
if (DocumentModel::Entry *entry = DocumentModelPrivate::addSuspendedDocument(fileName, displayName, id))
|
||||
DocumentModelPrivate::setPinned(entry, pinned);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -128,7 +128,9 @@ public:
|
||||
static bool closeDocument(IDocument *document, bool askAboutModifiedEditors = true);
|
||||
static bool closeDocuments(const QList<IDocument *> &documents, bool askAboutModifiedEditors = true);
|
||||
static void closeDocument(DocumentModel::Entry *entry);
|
||||
static void closeDocuments(const QList<DocumentModel::Entry *> &entries);
|
||||
static void closeOtherDocuments(IDocument *document);
|
||||
static void closeAllDocuments();
|
||||
|
||||
static void addCurrentPositionToNavigationHistory(const QByteArray &saveState = QByteArray());
|
||||
static void cutForwardNavigationHistory();
|
||||
@@ -161,6 +163,7 @@ public:
|
||||
|
||||
static void addSaveAndCloseEditorActions(QMenu *contextMenu, DocumentModel::Entry *entry,
|
||||
IEditor *editor = nullptr);
|
||||
static void addPinEditorActions(QMenu *contextMenu, DocumentModel::Entry *entry);
|
||||
static void addNativeDirAndOpenWithActions(QMenu *contextMenu, DocumentModel::Entry *entry);
|
||||
static void populateOpenWithMenu(QMenu *menu, const QString &fileName);
|
||||
|
||||
|
||||
@@ -180,6 +180,8 @@ private:
|
||||
static void openTerminal();
|
||||
static void findInDirectory();
|
||||
|
||||
static void togglePinned();
|
||||
|
||||
static void removeCurrentSplit();
|
||||
|
||||
static void setCurrentEditorFromContextChange();
|
||||
@@ -251,6 +253,7 @@ private:
|
||||
QAction *m_openTerminalAction;
|
||||
QAction *m_findInDirectoryAction;
|
||||
QAction *m_filePropertiesAction = nullptr;
|
||||
QAction *m_pinAction = nullptr;
|
||||
DocumentModel::Entry *m_contextMenuEntry = nullptr;
|
||||
IEditor *m_contextMenuEditor = nullptr;
|
||||
|
||||
|
||||
@@ -115,10 +115,12 @@ void OpenEditorsWidget::contextMenuRequested(QPoint pos)
|
||||
{
|
||||
QMenu contextMenu;
|
||||
QModelIndex editorIndex = indexAt(pos);
|
||||
DocumentModel::Entry *entry = DocumentModel::entryAtRow(
|
||||
m_model->mapToSource(editorIndex).row());
|
||||
const int row = m_model->mapToSource(editorIndex).row();
|
||||
DocumentModel::Entry *entry = DocumentModel::entryAtRow(row);
|
||||
EditorManager::addSaveAndCloseEditorActions(&contextMenu, entry);
|
||||
contextMenu.addSeparator();
|
||||
EditorManager::addPinEditorActions(&contextMenu, entry);
|
||||
contextMenu.addSeparator();
|
||||
EditorManager::addNativeDirAndOpenWithActions(&contextMenu, entry);
|
||||
contextMenu.exec(mapToGlobal(pos));
|
||||
}
|
||||
|
||||
@@ -354,6 +354,8 @@ void EditorToolBar::fillListContextMenu(QMenu *menu)
|
||||
: nullptr;
|
||||
EditorManager::addSaveAndCloseEditorActions(menu, entry, editor);
|
||||
menu->addSeparator();
|
||||
EditorManager::addPinEditorActions(menu, entry);
|
||||
menu->addSeparator();
|
||||
EditorManager::addNativeDirAndOpenWithActions(menu, entry);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -79,6 +79,7 @@ public:
|
||||
bool hasWriteWarning = false;
|
||||
bool restored = false;
|
||||
bool isSuspendAllowed = false;
|
||||
bool pinned = false;
|
||||
};
|
||||
|
||||
} // namespace Internal
|
||||
|
||||
@@ -159,7 +159,7 @@ void ShortCutManager::registerActions(const Core::Context &qmlDesignerMainContex
|
||||
|
||||
//Close All
|
||||
Core::ActionManager::registerAction(&m_closeAllEditorsAction, Core::Constants::CLOSEALL, qmlDesignerMainContext);
|
||||
connect(&m_closeAllEditorsAction, &QAction::triggered, em, &Core::EditorManager::closeAllEditors);
|
||||
connect(&m_closeAllEditorsAction, &QAction::triggered, em, &Core::EditorManager::closeAllDocuments);
|
||||
|
||||
//Close All Others Action
|
||||
Core::ActionManager::registerAction(&m_closeOtherEditorsAction, Core::Constants::CLOSEOTHERS, qmlDesignerMainContext);
|
||||
|
||||
@@ -6597,6 +6597,24 @@
|
||||
d="m 210,595 -2.5,2.5 -2.5,-2.5 z"
|
||||
style="fill:#000000;fill-opacity:1;stroke:none" />
|
||||
</g>
|
||||
<g
|
||||
id="src/libs/utils/images/pinned">
|
||||
<use
|
||||
style="display:inline"
|
||||
x="0"
|
||||
y="0"
|
||||
xlink:href="#backgroundRect"
|
||||
id="use5933-0-2-3"
|
||||
width="100%"
|
||||
height="100%"
|
||||
transform="translate(361,148)" />
|
||||
<path
|
||||
sodipodi:nodetypes="ccccccccccccccc"
|
||||
inkscape:connector-curvature="0"
|
||||
id="path6750"
|
||||
d="m 347,597.33936 0.60019,0.60645 3.49128,-3.49127 3.09695,3.09695 c 0.29088,-0.96173 0.20375,-2.0863 -0.1875,-3.07155 l 3.68179,-3.68179 0.55968,0.52841 0.75761,-0.75762 -4.51473,-4.51475 -0.80193,0.80194 0.53076,0.51509 -3.60205,3.60206 c -1.04768,-0.37523 -2.22553,-0.48941 -3.20237,-0.15625 l 3.0615,3.0615 z"
|
||||
style="fill:#000000" />
|
||||
</g>
|
||||
</g>
|
||||
<g
|
||||
inkscape:groupmode="layer"
|
||||
|
||||
|
Before Width: | Height: | Size: 373 KiB After Width: | Height: | Size: 374 KiB |
@@ -80,7 +80,10 @@ exists(perfparser/perfparser.pro) {
|
||||
cache(PERFPARSER_APP_INSTALLDIR)
|
||||
}
|
||||
|
||||
OTHER_FILES += tools.qbs
|
||||
OTHER_FILES += \
|
||||
tools.qbs \
|
||||
icons/exportapplicationicons.sh \
|
||||
icons/exportdocumenttypeicons.sh
|
||||
|
||||
# delegate deployqt target
|
||||
deployqt.CONFIG += recursive
|
||||
|
||||
Reference in New Issue
Block a user