resourceeditorplugin.cpp 15.1 KB
Newer Older
hjk's avatar
hjk committed
1
/****************************************************************************
con's avatar
con committed
2
**
3
** Copyright (C) 2014 Digia Plc and/or its subsidiary(-ies).
hjk's avatar
hjk committed
4
** Contact: http://www.qt-project.org/legal
con's avatar
con committed
5
**
hjk's avatar
hjk committed
6
** This file is part of Qt Creator.
con's avatar
con committed
7
**
hjk's avatar
hjk committed
8 9 10 11 12 13 14
** 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.
15
**
16
** GNU Lesser General Public License Usage
hjk's avatar
hjk committed
17 18 19 20 21 22 23 24 25
** 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
con's avatar
con committed
26 27
** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
**
hjk's avatar
hjk committed
28
****************************************************************************/
hjk's avatar
hjk committed
29

con's avatar
con committed
30
#include "resourceeditorplugin.h"
hjk's avatar
hjk committed
31

con's avatar
con committed
32 33 34
#include "resourceeditorw.h"
#include "resourceeditorconstants.h"
#include "resourceeditorfactory.h"
Daniel Teske's avatar
Daniel Teske committed
35
#include "resourcenode.h"
con's avatar
con committed
36 37 38 39

#include <coreplugin/icore.h>
#include <coreplugin/mimedatabase.h>
#include <coreplugin/coreconstants.h>
40
#include <coreplugin/id.h>
Daniel Teske's avatar
Daniel Teske committed
41
#include <coreplugin/actionmanager/actioncontainer.h>
42
#include <coreplugin/actionmanager/actionmanager.h>
con's avatar
con committed
43
#include <coreplugin/editormanager/editormanager.h>
Daniel Teske's avatar
Daniel Teske committed
44 45 46 47
#include <projectexplorer/project.h>
#include <projectexplorer/projectexplorer.h>
#include <projectexplorer/projectexplorerconstants.h>
#include <projectexplorer/projectnodes.h>
48
#include <extensionsystem/pluginmanager.h>
con's avatar
con committed
49

50
#include <utils/parameteraction.h>
hjk's avatar
hjk committed
51 52
#include <utils/qtcassert.h>

53 54 55
#include <QtPlugin>
#include <QCoreApplication>
#include <QAction>
Daniel Teske's avatar
Daniel Teske committed
56 57 58 59 60
#include <QDebug>
#include <QInputDialog>
#include <QMessageBox>
#include <QFormLayout>
#include <QDialogButtonBox>
61 62
#include <QClipboard>
#include <QApplication>
con's avatar
con committed
63

64 65 66 67
using namespace ProjectExplorer;

namespace ResourceEditor {
namespace Internal {
con's avatar
con committed
68

69
static const char resourcePrefix[] = ":";
70
static const char urlPrefix[] = "qrc:";
71

Daniel Teske's avatar
Daniel Teske committed
72 73
class PrefixLangDialog : public QDialog
{
74
    Q_OBJECT
Daniel Teske's avatar
Daniel Teske committed
75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90
public:
    PrefixLangDialog(const QString &title, const QString &prefix, const QString &lang, QWidget *parent)
        : QDialog(parent)
    {
        setWindowTitle(title);
        QFormLayout *layout = new QFormLayout(this);
        m_prefixLineEdit = new QLineEdit(this);
        m_prefixLineEdit->setText(prefix);
        layout->addRow(tr("Prefix:"), m_prefixLineEdit);

        m_langLineEdit = new QLineEdit(this);
        m_langLineEdit->setText(lang);
        layout->addRow(tr("Language:"), m_langLineEdit);

        QDialogButtonBox *buttons = new QDialogButtonBox(QDialogButtonBox::Ok
                                                         | QDialogButtonBox::Cancel,
Orgad Shaneh's avatar
Orgad Shaneh committed
91
                                                         Qt::Horizontal,
Daniel Teske's avatar
Daniel Teske committed
92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114
                                                         this);

        layout->addWidget(buttons);

        connect(buttons, SIGNAL(accepted()),
                this, SLOT(accept()));
        connect(buttons, SIGNAL(rejected()),
                this, SLOT(reject()));
    }
    QString prefix() const
    {
        return m_prefixLineEdit->text();
    }

    QString lang() const
    {
        return m_langLineEdit->text();
    }
private:
    QLineEdit *m_prefixLineEdit;
    QLineEdit *m_langLineEdit;
};

con's avatar
con committed
115
ResourceEditorPlugin::ResourceEditorPlugin() :
116 117
    m_redoAction(0),
    m_undoAction(0)
con's avatar
con committed
118 119 120
{
}

121
bool ResourceEditorPlugin::initialize(const QStringList &arguments, QString *errorMessage)
con's avatar
con committed
122
{
123
    Q_UNUSED(arguments)
hjk's avatar
hjk committed
124
    if (!Core::MimeDatabase::addMimeTypes(QLatin1String(":/resourceeditor/ResourceEditor.mimetypes.xml"), errorMessage))
con's avatar
con committed
125 126
        return false;

127 128
    ResourceEditorFactory *editor = new ResourceEditorFactory(this);
    addAutoReleasedObject(editor);
con's avatar
con committed
129

130
    errorMessage->clear();
con's avatar
con committed
131 132

    // Register undo and redo
133
    const Core::Context context(Constants::C_RESOURCEEDITOR);
con's avatar
con committed
134 135
    m_undoAction = new QAction(tr("&Undo"), this);
    m_redoAction = new QAction(tr("&Redo"), this);
136
    m_refreshAction = new QAction(tr("Recheck Existence of Referenced Files"), this);
Eike Ziller's avatar
Eike Ziller committed
137 138
    Core::ActionManager::registerAction(m_undoAction, Core::Constants::UNDO, context);
    Core::ActionManager::registerAction(m_redoAction, Core::Constants::REDO, context);
139
    Core::ActionManager::registerAction(m_refreshAction, Constants::REFRESH, context);
con's avatar
con committed
140 141
    connect(m_undoAction, SIGNAL(triggered()), this, SLOT(onUndo()));
    connect(m_redoAction, SIGNAL(triggered()), this, SLOT(onRedo()));
142
    connect(m_refreshAction, SIGNAL(triggered()), this, SLOT(onRefresh()));
con's avatar
con committed
143

Daniel Teske's avatar
Daniel Teske committed
144 145 146
    Core::Context projectTreeContext(ProjectExplorer::Constants::C_PROJECT_TREE);
    Core::ActionContainer *folderContextMenu =
            Core::ActionManager::actionContainer(ProjectExplorer::Constants::M_FOLDERCONTEXT);
147 148
    Core::ActionContainer *fileContextMenu =
            Core::ActionManager::actionContainer(ProjectExplorer::Constants::M_FILECONTEXT);
Daniel Teske's avatar
Daniel Teske committed
149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165
    Core::Command *command = 0;

    m_addPrefix = new QAction(tr("Add Prefix..."), this);
    command = Core::ActionManager::registerAction(m_addPrefix, Constants::C_ADD_PREFIX, projectTreeContext);
    folderContextMenu->addAction(command, ProjectExplorer::Constants::G_FOLDER_FILES);
    connect(m_addPrefix, SIGNAL(triggered()), this, SLOT(addPrefixContextMenu()));

    m_renamePrefix = new QAction(tr("Change Prefix..."), this);
    command = Core::ActionManager::registerAction(m_renamePrefix, Constants::C_RENAME_PREFIX, projectTreeContext);
    folderContextMenu->addAction(command, ProjectExplorer::Constants::G_FOLDER_FILES);
    connect(m_renamePrefix, SIGNAL(triggered()), this, SLOT(renamePrefixContextMenu()));

    m_removePrefix = new QAction(tr("Remove Prefix..."), this);
    command = Core::ActionManager::registerAction(m_removePrefix, Constants::C_REMOVE_PREFIX, projectTreeContext);
    folderContextMenu->addAction(command, ProjectExplorer::Constants::G_FOLDER_FILES);
    connect(m_removePrefix, SIGNAL(triggered()), this, SLOT(removePrefixContextMenu()));

166
    m_renameResourceFile = new QAction(tr("Rename..."), this);
Daniel Teske's avatar
Daniel Teske committed
167 168 169 170
    command = Core::ActionManager::registerAction(m_renameResourceFile, Constants::C_RENAME_FILE, projectTreeContext);
    folderContextMenu->addAction(command, ProjectExplorer::Constants::G_FOLDER_FILES);
    connect(m_renameResourceFile, SIGNAL(triggered()), this, SLOT(renameFileContextMenu()));

171
    m_removeResourceFile = new QAction(tr("Remove File..."), this);
Daniel Teske's avatar
Daniel Teske committed
172 173 174 175 176 177 178 179 180 181 182 183 184 185
    command = Core::ActionManager::registerAction(m_removeResourceFile, Constants::C_REMOVE_FILE, projectTreeContext);
    folderContextMenu->addAction(command, ProjectExplorer::Constants::G_FOLDER_FILES);
    connect(m_removeResourceFile, SIGNAL(triggered()), this, SLOT(removeFileContextMenu()));

    m_openInEditor = new QAction(tr("Open in Editor"), this);
    command = Core::ActionManager::registerAction(m_openInEditor, Constants::C_OPEN_EDITOR, projectTreeContext);
    folderContextMenu->addAction(command, ProjectExplorer::Constants::G_FOLDER_FILES);
    connect(m_openInEditor, SIGNAL(triggered()), this, SLOT(openEditorContextMenu()));

    m_openInTextEditor = new QAction(tr("Open in Text Editor"), this);
    command = Core::ActionManager::registerAction(m_openInTextEditor, Constants::C_OPEN_TEXT_EDITOR, projectTreeContext);
    folderContextMenu->addAction(command, ProjectExplorer::Constants::G_FOLDER_FILES);
    connect(m_openInTextEditor, SIGNAL(triggered()), this, SLOT(openTextEditorContextMenu()));

186 187 188 189 190 191 192 193 194 195 196 197
    m_copyPath = new Utils::ParameterAction(QString(), tr("Copy path \"%1\""), Utils::ParameterAction::AlwaysEnabled, this);
    command = Core::ActionManager::registerAction(m_copyPath, Constants::C_COPY_PATH, projectTreeContext);
    command->setAttribute(Core::Command::CA_UpdateText);
    fileContextMenu->addAction(command, ProjectExplorer::Constants::G_FILE_OTHER);
    connect(m_copyPath, SIGNAL(triggered()), this, SLOT(copyPathContextMenu()));

    m_copyUrl = new Utils::ParameterAction(QString(), tr("Copy url \"%1\""), Utils::ParameterAction::AlwaysEnabled, this);
    command = Core::ActionManager::registerAction(m_copyUrl, Constants::C_COPY_URL, projectTreeContext);
    command->setAttribute(Core::Command::CA_UpdateText);
    fileContextMenu->addAction(command, ProjectExplorer::Constants::G_FILE_OTHER);
    connect(m_copyUrl, SIGNAL(triggered()), this, SLOT(copyUrlContextMenu()));

Daniel Teske's avatar
Daniel Teske committed
198 199 200 201 202 203 204 205 206 207
    m_addPrefix->setEnabled(false);
    m_removePrefix->setEnabled(false);
    m_renamePrefix->setEnabled(false);
    m_renameResourceFile->setEnabled(false);
    m_removeResourceFile->setEnabled(false);

    connect(ProjectExplorer::ProjectExplorerPlugin::instance(), SIGNAL(currentNodeChanged(ProjectExplorer::Node*,ProjectExplorer::Project*)),
            this, SLOT(updateContextActions(ProjectExplorer::Node*,ProjectExplorer::Project*)));


con's avatar
con committed
208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224
    return true;
}

void ResourceEditorPlugin::extensionsInitialized()
{
}

void ResourceEditorPlugin::onUndo()
{
    currentEditor()->onUndo();
}

void ResourceEditorPlugin::onRedo()
{
    currentEditor()->onRedo();
}

225 226 227 228 229
void ResourceEditorPlugin::onRefresh()
{
    currentEditor()->onRefresh();
}

Daniel Teske's avatar
Daniel Teske committed
230 231 232 233 234 235 236 237
void ResourceEditorPlugin::addPrefixContextMenu()
{
    PrefixLangDialog dialog(tr("Add Prefix"), QString(), QString(), Core::ICore::mainWindow());
    if (dialog.exec() != QDialog::Accepted)
        return;
    QString prefix = dialog.prefix();
    if (prefix.isEmpty())
        return;
238
    ResourceTopLevelNode *topLevel = static_cast<ResourceTopLevelNode *>(ProjectExplorer::ProjectExplorerPlugin::currentNode());
Daniel Teske's avatar
Daniel Teske committed
239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255
    topLevel->addPrefix(prefix, dialog.lang());
}

void ResourceEditorPlugin::removePrefixContextMenu()
{
    ResourceFolderNode *rfn = static_cast<ResourceFolderNode *>(ProjectExplorer::ProjectExplorerPlugin::instance()->currentNode());
    if (QMessageBox::question(Core::ICore::mainWindow(),
                              tr("Remove Prefix"),
                              tr("Remove prefix %1 and all its files?").arg(rfn->displayName()))
            == QMessageBox::Yes) {
        ResourceTopLevelNode *rn = rfn->resourceNode();
        rn->removePrefix(rfn->prefix(), rfn->lang());
    }
}

void ResourceEditorPlugin::renameFileContextMenu()
{
256
    ProjectExplorerPlugin::initiateInlineRenaming();
Daniel Teske's avatar
Daniel Teske committed
257 258 259 260 261 262 263 264 265
}

void ResourceEditorPlugin::removeFileContextMenu()
{
    ResourceFolderNode *rfn = static_cast<ResourceFolderNode *>(ProjectExplorer::ProjectExplorerPlugin::instance()->currentNode());
    QString path = rfn->path();
    ProjectExplorer::FolderNode *parent = rfn->parentFolderNode();
    if (!parent->removeFiles(QStringList() << path))
        QMessageBox::warning(Core::ICore::mainWindow(),
266
                             tr("File Removal Failed"),
Daniel Teske's avatar
Daniel Teske committed
267 268 269 270 271 272 273 274 275 276 277 278
                             tr("Removing file %1 from the project failed.").arg(path));
}

void ResourceEditorPlugin::openEditorContextMenu()
{
    ResourceTopLevelNode *topLevel = static_cast<ResourceTopLevelNode *>(ProjectExplorer::ProjectExplorerPlugin::instance()->currentNode());
    QString path = topLevel->path();
    Core::EditorManager::openEditor(path);
}

void ResourceEditorPlugin::openTextEditorContextMenu()
{
279
    ResourceTopLevelNode *topLevel = static_cast<ResourceTopLevelNode *>(ProjectExplorerPlugin::currentNode());
Daniel Teske's avatar
Daniel Teske committed
280 281 282 283
    QString path = topLevel->path();
    Core::EditorManager::openEditor(path, Core::Constants::K_DEFAULT_TEXT_EDITOR_ID);
}

284 285
void ResourceEditorPlugin::copyPathContextMenu()
{
286
    ResourceFileNode *node = static_cast<ResourceFileNode *>(ProjectExplorerPlugin::currentNode());
287 288 289 290 291
    QApplication::clipboard()->setText(QLatin1String(resourcePrefix) + node->qrcPath());
}

void ResourceEditorPlugin::copyUrlContextMenu()
{
292
    ResourceFileNode *node = static_cast<ResourceFileNode *>(ProjectExplorerPlugin::currentNode());
293 294 295
    QApplication::clipboard()->setText(QLatin1String(urlPrefix) + node->qrcPath());
}

Daniel Teske's avatar
Daniel Teske committed
296 297
void ResourceEditorPlugin::renamePrefixContextMenu()
{
298
    ResourceFolderNode *node = static_cast<ResourceFolderNode *>(ProjectExplorerPlugin::currentNode());
Daniel Teske's avatar
Daniel Teske committed
299

300
    PrefixLangDialog dialog(tr("Rename Prefix"), node->prefix(), node->lang(), Core::ICore::mainWindow());
Daniel Teske's avatar
Daniel Teske committed
301 302 303 304 305 306
    if (dialog.exec() != QDialog::Accepted)
        return;
    QString prefix = dialog.prefix();
    if (prefix.isEmpty())
        return;

307
    node->renamePrefix(prefix, dialog.lang());
Daniel Teske's avatar
Daniel Teske committed
308 309 310 311 312 313 314 315 316 317 318 319 320 321 322 323 324 325 326 327 328 329 330 331 332 333 334 335 336 337 338 339 340 341
}

void ResourceEditorPlugin::updateContextActions(ProjectExplorer::Node *node, ProjectExplorer::Project *)
{
    bool isResourceNode = qobject_cast<ResourceTopLevelNode *>(node);
    m_addPrefix->setEnabled(isResourceNode);
    m_addPrefix->setVisible(isResourceNode);

    bool enableRename = false;
    bool enableRemove = false;

    if (isResourceNode) {
        ProjectExplorer::FolderNode *parent = node ? node->parentFolderNode() : 0;
        enableRename = parent && parent->supportedActions(node).contains(ProjectExplorer::Rename);
        enableRemove = parent && parent->supportedActions(node).contains(ProjectExplorer::RemoveFile);
    }

    m_renameResourceFile->setEnabled(isResourceNode && enableRename);
    m_renameResourceFile->setVisible(isResourceNode && enableRename);
    m_removeResourceFile->setEnabled(isResourceNode && enableRemove);
    m_removeResourceFile->setVisible(isResourceNode && enableRemove);

    m_openInEditor->setEnabled(isResourceNode);
    m_openInEditor->setVisible(isResourceNode);

    m_openInTextEditor->setEnabled(isResourceNode);
    m_openInTextEditor->setVisible(isResourceNode);

    bool isResourceFolder = qobject_cast<ResourceFolderNode *>(node);
    m_removePrefix->setEnabled(isResourceFolder);
    m_removePrefix->setVisible(isResourceFolder);

    m_renamePrefix->setEnabled(isResourceFolder);
    m_renamePrefix->setVisible(isResourceFolder);
342 343 344 345 346 347 348 349 350 351 352 353

    bool isResourceFile = qobject_cast<ResourceFileNode *>(node);
    m_copyPath->setEnabled(isResourceFile);
    m_copyPath->setVisible(isResourceFile);
    m_copyUrl->setEnabled(isResourceFile);
    m_copyUrl->setVisible(isResourceFile);
    if (isResourceFile) {
        ResourceFileNode *fileNode = static_cast<ResourceFileNode *>(node);
        QString qrcPath = fileNode->qrcPath();
        m_copyPath->setParameter(QLatin1String(resourcePrefix) + qrcPath);
        m_copyUrl->setParameter(QLatin1String(urlPrefix) + qrcPath);
    }
Daniel Teske's avatar
Daniel Teske committed
354 355
}

con's avatar
con committed
356 357 358 359 360 361 362 363 364
void ResourceEditorPlugin::onUndoStackChanged(ResourceEditorW const *editor,
        bool canUndo, bool canRedo)
{
    if (editor == currentEditor()) {
        m_undoAction->setEnabled(canUndo);
        m_redoAction->setEnabled(canRedo);
    }
}

hjk's avatar
hjk committed
365 366
ResourceEditorW * ResourceEditorPlugin::currentEditor() const
{
con's avatar
con committed
367
    ResourceEditorW * const focusEditor = qobject_cast<ResourceEditorW *>(
hjk's avatar
hjk committed
368
            Core::EditorManager::currentEditor());
hjk's avatar
hjk committed
369
    QTC_ASSERT(focusEditor, return 0);
con's avatar
con committed
370 371 372
    return focusEditor;
}

373 374 375
} // namespace Internal
} // namespace ResourceEditor

376
#include "resourceeditorplugin.moc"