summaryrefslogtreecommitdiff
path: root/src/plugins
diff options
context:
space:
mode:
Diffstat (limited to 'src/plugins')
-rw-r--r--src/plugins/coreplugin/coreconstants.h2
-rw-r--r--src/plugins/coreplugin/editormanager/editormanager.h4
-rw-r--r--src/plugins/coreplugin/mainwindow.cpp1
-rw-r--r--src/plugins/coreplugin/navigationwidget.cpp7
-rw-r--r--src/plugins/coreplugin/outputpane.cpp10
-rw-r--r--src/plugins/cppeditor/cpphoverhandler.cpp10
-rw-r--r--src/plugins/cpptools/cpptoolsplugin.cpp5
-rw-r--r--src/plugins/debugger/debugger.pro1
-rw-r--r--src/plugins/debugger/gdbengine.cpp43
-rw-r--r--src/plugins/debugger/gdbengine.h1
-rw-r--r--src/plugins/debugger/mode.ui76
-rw-r--r--src/plugins/fakevim/fakevimplugin.cpp42
-rw-r--r--src/plugins/fakevim/fakevimplugin.h20
-rw-r--r--src/plugins/fakevim/handler.cpp656
-rw-r--r--src/plugins/fakevim/handler.h4
-rw-r--r--src/plugins/find/currentdocumentfind.cpp4
-rw-r--r--src/plugins/git/branchdialog.cpp17
-rw-r--r--src/plugins/git/branchdialog.h8
-rw-r--r--src/plugins/git/branchmodel.cpp192
-rw-r--r--src/plugins/git/branchmodel.h79
-rw-r--r--src/plugins/help/helpplugin.cpp5
-rw-r--r--src/plugins/qt4projectmanager/qt4project.cpp1
-rw-r--r--src/plugins/quickopen/quickopentoolwindow.cpp17
-rw-r--r--src/plugins/texteditor/completionwidget.cpp4
24 files changed, 852 insertions, 357 deletions
diff --git a/src/plugins/coreplugin/coreconstants.h b/src/plugins/coreplugin/coreconstants.h
index 857dd5be37..301cfb6d39 100644
--- a/src/plugins/coreplugin/coreconstants.h
+++ b/src/plugins/coreplugin/coreconstants.h
@@ -52,7 +52,7 @@ namespace Constants {
const char * const IDE_VERSION_LONG = IDE_VERSION;
const char * const IDE_AUTHOR = "Nokia Corporation";
-const char * const IDE_YEAR = "2008";
+const char * const IDE_YEAR = "2009";
#ifdef IDE_REVISION
const char * const IDE_REVISION_STR = STRINGIFY(IDE_REVISION);
diff --git a/src/plugins/coreplugin/editormanager/editormanager.h b/src/plugins/coreplugin/editormanager/editormanager.h
index 729ac7cd84..eec20a4a05 100644
--- a/src/plugins/coreplugin/editormanager/editormanager.h
+++ b/src/plugins/coreplugin/editormanager/editormanager.h
@@ -65,6 +65,7 @@ enum MakeWritableResult {
};
struct EditorManagerPrivate;
+
namespace Internal {
class OpenEditorsWindow;
class EditorSplitter;
@@ -224,7 +225,8 @@ private:
namespace Internal {
-class EditorClosingCoreListener : public ICoreListener {
+class EditorClosingCoreListener : public ICoreListener
+{
Q_OBJECT
public:
diff --git a/src/plugins/coreplugin/mainwindow.cpp b/src/plugins/coreplugin/mainwindow.cpp
index 2a9fff0f4e..f68c5da7d0 100644
--- a/src/plugins/coreplugin/mainwindow.cpp
+++ b/src/plugins/coreplugin/mainwindow.cpp
@@ -625,6 +625,7 @@ void MainWindow::registerDefaultActions()
// Toggle Sidebar Action
m_toggleSideBarAction = new QAction(QIcon(Constants::ICON_TOGGLE_SIDEBAR),
tr("Toggle Sidebar"), this);
+ m_toggleSideBarAction->setCheckable(true);
cmd = am->registerAction(m_toggleSideBarAction, Constants::TOGGLE_SIDEBAR, m_globalContext);
#ifdef Q_OS_MAC
cmd->setDefaultKeySequence(QKeySequence("Ctrl+0"));
diff --git a/src/plugins/coreplugin/navigationwidget.cpp b/src/plugins/coreplugin/navigationwidget.cpp
index 9bbb4323d2..412559a9b0 100644
--- a/src/plugins/coreplugin/navigationwidget.cpp
+++ b/src/plugins/coreplugin/navigationwidget.cpp
@@ -166,6 +166,7 @@ int NavigationWidget::storedWidth()
void NavigationWidget::placeHolderChanged(NavigationWidgetPlaceHolder *holder)
{
m_toggleSideBarAction->setEnabled(holder);
+ m_toggleSideBarAction->setChecked(holder && isShown());
}
void NavigationWidget::resizeEvent(QResizeEvent *re)
@@ -281,8 +282,12 @@ void NavigationWidget::setShown(bool b)
if (m_shown == b)
return;
m_shown = b;
- if (NavigationWidgetPlaceHolder::m_current)
+ if (NavigationWidgetPlaceHolder::m_current) {
NavigationWidgetPlaceHolder::m_current->setVisible(m_shown && !m_suppressed);
+ m_toggleSideBarAction->setChecked(m_shown);
+ } else {
+ m_toggleSideBarAction->setChecked(false);
+ }
}
bool NavigationWidget::isShown() const
diff --git a/src/plugins/coreplugin/outputpane.cpp b/src/plugins/coreplugin/outputpane.cpp
index b9cd825e24..6d97c5d361 100644
--- a/src/plugins/coreplugin/outputpane.cpp
+++ b/src/plugins/coreplugin/outputpane.cpp
@@ -488,13 +488,13 @@ OutputPaneToggleButton::OutputPaneToggleButton(int number, const QString &text,
setFocusPolicy(Qt::NoFocus);
setCheckable(true);
setStyleSheet(
- "QPushButton { border-image: url(:/qworkbench/images/panel_button.png) 2 2 2 19 repeat;"
+ "QPushButton { border-image: url(:/qworkbench/images/panel_button.png) 2 2 2 19;"
" border-width: 2px 2px 2px 19px; padding-left: -17; padding-right: 4 } "
- "QPushButton:checked { border-image: url(:/qworkbench/images/panel_button_checked.png) 2 2 2 19 repeat } "
+ "QPushButton:checked { border-image: url(:/qworkbench/images/panel_button_checked.png) 2 2 2 19 } "
#ifndef Q_WS_MAC // Mac UI's dont usually do hover
- "QPushButton:checked:hover { border-image: url(:/qworkbench/images/panel_button_checked_hover.png) 2 2 2 19 repeat } "
- "QPushButton:pressed:hover { border-image: url(:/qworkbench/images/panel_button_pressed.png) 2 2 2 19 repeat } "
- "QPushButton:hover { border-image: url(:/qworkbench/images/panel_button_hover.png) 2 2 2 19 repeat } "
+ "QPushButton:checked:hover { border-image: url(:/qworkbench/images/panel_button_checked_hover.png) 2 2 2 19 } "
+ "QPushButton:pressed:hover { border-image: url(:/qworkbench/images/panel_button_pressed.png) 2 2 2 19 } "
+ "QPushButton:hover { border-image: url(:/qworkbench/images/panel_button_hover.png) 2 2 2 19 } "
#endif
);
}
diff --git a/src/plugins/cppeditor/cpphoverhandler.cpp b/src/plugins/cppeditor/cpphoverhandler.cpp
index ba97e5a212..6ebf51b2a2 100644
--- a/src/plugins/cppeditor/cpphoverhandler.cpp
+++ b/src/plugins/cppeditor/cpphoverhandler.cpp
@@ -72,10 +72,16 @@ CppHoverHandler::CppHoverHandler(QObject *parent)
m_modelManager = m_core->pluginManager()->getObject<CppTools::CppModelManagerInterface>();
QFileInfo fi(ExtensionSystem::PluginManager::instance()->getObject<Core::ICore>()->settings()->fileName());
- m_helpEngine = new QHelpEngineCore(fi.absolutePath()
+ // FIXME shouldn't the help engine create the directory if it doesn't exist?
+ QDir directory(fi.absolutePath()+"/qtcreator");
+ if (!directory.exists())
+ directory.mkpath(directory.absolutePath());
+
+ m_helpEngine = new QHelpEngineCore(directory.absolutePath()
+ QLatin1String("/helpcollection.qhc"), this);
//m_helpEngine->setAutoSaveFilter(false);
- m_helpEngine->setupData();
+ if (!m_helpEngine->setupData())
+ qWarning() << "Could not initialize help engine:" << m_helpEngine->error();
m_helpEngine->setCurrentFilter(tr("Unfiltered"));
m_helpEngineNeedsSetup = m_helpEngine->registeredDocumentations().count() == 0;
diff --git a/src/plugins/cpptools/cpptoolsplugin.cpp b/src/plugins/cpptools/cpptoolsplugin.cpp
index 4195fbee33..866a3d05c9 100644
--- a/src/plugins/cpptools/cpptoolsplugin.cpp
+++ b/src/plugins/cpptools/cpptoolsplugin.cpp
@@ -163,7 +163,8 @@ QFileInfo CppToolsPlugin::findFile(const QDir &dir, const QString &name,
if (debug)
qDebug() << Q_FUNC_INFO << dir << name;
- if (project) {
+ QFileInfo fileInSameDir(dir, name);
+ if (project && !fileInSameDir.isFile()) {
QString pattern = QString(1, QLatin1Char('/'));
pattern += name;
const QStringList projectFiles = project->files(ProjectExplorer::Project::AllFiles);
@@ -173,7 +174,7 @@ QFileInfo CppToolsPlugin::findFile(const QDir &dir, const QString &name,
return QFileInfo(*it);
return QFileInfo();
}
- return QFileInfo(dir, name);
+ return fileInSameDir;
}
// Figure out file type
diff --git a/src/plugins/debugger/debugger.pro b/src/plugins/debugger/debugger.pro
index 7308fb441c..b47e7d5ee0 100644
--- a/src/plugins/debugger/debugger.pro
+++ b/src/plugins/debugger/debugger.pro
@@ -76,7 +76,6 @@ FORMS += attachexternaldialog.ui \
attachremotedialog.ui \
breakbyfunction.ui \
breakcondition.ui \
- mode.ui \
gdboptionpage.ui \
startexternaldialog.ui \
diff --git a/src/plugins/debugger/gdbengine.cpp b/src/plugins/debugger/gdbengine.cpp
index 7c7d3b6d32..fa6f9ab325 100644
--- a/src/plugins/debugger/gdbengine.cpp
+++ b/src/plugins/debugger/gdbengine.cpp
@@ -2944,8 +2944,8 @@ void GdbEngine::runCustomDumper(const WatchData & data0, bool dumpChildren)
QString outertype = isTemplate ? tmplate : data.type;
// adjust the data extract
- if (outertype == "QWidget")
- outertype = "QObject";
+ if (outertype == m_namespace + "QWidget")
+ outertype = m_namespace + "QObject";
QString extraArgs[4];
extraArgs[0] = "0";
@@ -2977,10 +2977,17 @@ void GdbEngine::runCustomDumper(const WatchData & data0, bool dumpChildren)
if (lastOpened != -1 && lastClosed != -1)
slotNumber = data.iname.mid(lastOpened + 1, lastClosed - lastOpened - 1);
extraArgs[0] = slotNumber;
- } else if (outertype == m_namespace + "QMap") {
- QString nodetype = m_namespace + "QMapNode";
- nodetype += data.type.mid(m_namespace.size() + 4);
- //qDebug() << "OUTERTYPE: " << outertype << " NODETYPE: " << nodetype;
+ } else if (outertype == m_namespace + "QMap" || outertype == m_namespace + "QMultiMap") {
+ QString nodetype;
+ if (m_qtVersion >= (4 << 16) + (5 << 8) + 0) {
+ nodetype = m_namespace + "QMapNode";
+ nodetype += data.type.mid(outertype.size());
+ } else {
+ // FIXME: doesn't work for QMultiMap
+ nodetype = data.type + "::Node";
+ }
+ //qDebug() << "OUTERTYPE: " << outertype << " NODETYPE: " << nodetype
+ // << "QT VERSION" << m_qtVersion << ((4 << 16) + (5 << 8) + 0);
extraArgs[2] = sizeofTypeExpression(nodetype);
extraArgs[3] = "(size_t)&(('" + nodetype + "'*)0)->value";
} else if (outertype == m_namespace + "QMapNode") {
@@ -3311,6 +3318,16 @@ void GdbEngine::handleQueryDataDumper2(const GdbResultRecord &record)
GdbMi contents(output.data());
GdbMi simple = contents.findChild("dumpers");
m_namespace = contents.findChild("namespace").data();
+ GdbMi qtversion = contents.findChild("qtversion");
+ if (qtversion.children().size() == 3) {
+ m_qtVersion = (qtversion.childAt(0).data().toInt() << 16)
+ + (qtversion.childAt(1).data().toInt() << 8)
+ + qtversion.childAt(2).data().toInt();
+ //qDebug() << "FOUND QT VERSION: " << qtversion.toString() << m_qtVersion;
+ } else {
+ m_qtVersion = 0;
+ }
+
//qDebug() << "OUTPUT: " << output.toString();
//qDebug() << "CONTENTS: " << contents.toString();
//qDebug() << "SIMPLE DUMPERS: " << simple.toString();
@@ -3536,8 +3553,9 @@ void GdbEngine::handleDumpCustomValue2(const GdbResultRecord &record,
// << item.findChild("nameencoded").data()[1];
if (item.findChild("nameencoded").data()[0] == '1')
data1.name = QByteArray::fromBase64(data1.name.toUtf8());
- if (item.findChild("nameisindex").data()[0] == '1')
- data1.name = '[' + data1.name + ']';
+ QString key = item.findChild("key").data();
+ if (!key.isEmpty())
+ data1.name += " (" + key + ")";
setWatchDataType(data1, item.findChild("type"));
setWatchDataExpression(data1, item.findChild("exp"));
setWatchDataChildCount(data1, item.findChild("numchild"));
@@ -3951,6 +3969,9 @@ void GdbEngine::tryLoadCustomDumpers()
sendCommand("sharedlibrary " + dotEscape(lib));
if (qq->useFastStart())
sendCommand("set stop-on-solib-events 1");
+ } else {
+ qDebug() << "DEBUG HELPER LIBRARY IS NOT USABLE: "
+ << lib << QFileInfo(lib).isExecutable();
}
#endif
#if defined(Q_OS_MAC)
@@ -3964,6 +3985,9 @@ void GdbEngine::tryLoadCustomDumpers()
sendCommand("sharedlibrary " + dotEscape(lib));
if (qq->useFastStart())
sendCommand("set stop-on-solib-events 1");
+ } else {
+ qDebug() << "DEBUG HELPER LIBRARY IS NOT USABLE: "
+ << lib << QFileInfo(lib).isExecutable();
}
#endif
#if defined(Q_OS_WIN)
@@ -3977,6 +4001,9 @@ void GdbEngine::tryLoadCustomDumpers()
sendCommand("sharedlibrary " + dotEscape(lib));
if (qq->useFastStart())
sendCommand("set stop-on-solib-events 1");
+ } else {
+ qDebug() << "DEBUG HELPER LIBRARY IS NOT USABLE: "
+ << lib << QFileInfo(lib).isExecutable();
}
#endif
diff --git a/src/plugins/debugger/gdbengine.h b/src/plugins/debugger/gdbengine.h
index c1344f86dd..000c0b84a9 100644
--- a/src/plugins/debugger/gdbengine.h
+++ b/src/plugins/debugger/gdbengine.h
@@ -333,6 +333,7 @@ private:
QStringList m_availableSimpleDumpers;
QString m_namespace; // namespace used in "namespaced Qt";
+ int m_qtVersion; // Qt version used in the debugged program
DataDumperState m_dataDumperState; // state of qt creator dumpers
QList<GdbMi> m_currentFunctionArgs;
diff --git a/src/plugins/debugger/mode.ui b/src/plugins/debugger/mode.ui
deleted file mode 100644
index da44cf38b4..0000000000
--- a/src/plugins/debugger/mode.ui
+++ /dev/null
@@ -1,76 +0,0 @@
-<ui version="4.0" >
- <class>DebugMode</class>
- <widget class="QWidget" name="DebugMode" >
- <property name="geometry" >
- <rect>
- <x>0</x>
- <y>0</y>
- <width>558</width>
- <height>353</height>
- </rect>
- </property>
- <property name="windowTitle" >
- <string>Form</string>
- </property>
- <layout class="QVBoxLayout" name="verticalLayout_3" >
- <property name="spacing" >
- <number>0</number>
- </property>
- <property name="margin" >
- <number>0</number>
- </property>
- <item>
- <widget class="QSplitter" name="vSplitter" >
- <property name="orientation" >
- <enum>Qt::Vertical</enum>
- </property>
- <widget class="QWidget" native="1" name="editorHolder" >
- <property name="sizePolicy" >
- <sizepolicy vsizetype="Preferred" hsizetype="Preferred" >
- <horstretch>10</horstretch>
- <verstretch>10</verstretch>
- </sizepolicy>
- </property>
- </widget>
- <widget class="QWidget" name="layoutWidget" >
- <layout class="QVBoxLayout" name="verticalLayout" >
- <property name="spacing" >
- <number>0</number>
- </property>
- <item>
- <layout class="QVBoxLayout" name="toolbarLayout" >
- <property name="spacing" >
- <number>0</number>
- </property>
- </layout>
- </item>
- <item>
- <widget class="QSplitter" name="hSplitter" >
- <property name="orientation" >
- <enum>Qt::Horizontal</enum>
- </property>
- <widget class="QTabWidget" name="bottomTabWidget" >
- <property name="sizePolicy" >
- <sizepolicy vsizetype="Expanding" hsizetype="Expanding" >
- <horstretch>0</horstretch>
- <verstretch>0</verstretch>
- </sizepolicy>
- </property>
- <property name="tabPosition" >
- <enum>QTabWidget::South</enum>
- </property>
- <property name="tabShape" >
- <enum>QTabWidget::Rounded</enum>
- </property>
- </widget>
- </widget>
- </item>
- </layout>
- </widget>
- </widget>
- </item>
- </layout>
- </widget>
- <resources/>
- <connections/>
-</ui>
diff --git a/src/plugins/fakevim/fakevimplugin.cpp b/src/plugins/fakevim/fakevimplugin.cpp
index 20b3b082a5..97e1cfffea 100644
--- a/src/plugins/fakevim/fakevimplugin.cpp
+++ b/src/plugins/fakevim/fakevimplugin.cpp
@@ -75,6 +75,7 @@ namespace FakeVim {
namespace Constants {
const char * const INSTALL_HANDLER = "FakeVim.InstallHandler";
+const char * const MINI_BUFFER = "FakeVim.MiniBuffer";
const char * const INSTALL_KEY = "Alt+V,Alt+V";
} // namespace Constants
@@ -89,7 +90,7 @@ const char * const INSTALL_KEY = "Alt+V,Alt+V";
FakeVimPlugin::FakeVimPlugin()
{
- m_pm = 0;
+ m_core = 0;
m_handler = 0;
}
@@ -109,12 +110,10 @@ bool FakeVimPlugin::initialize(const QStringList &arguments, QString *error_mess
m_handler = new FakeVimHandler;
- m_pm = ExtensionSystem::PluginManager::instance();
+ m_core = ExtensionSystem::PluginManager::instance()->getObject<Core::ICore>();
+ QTC_ASSERT(m_core, return false);
- ICore *core = m_pm->getObject<Core::ICore>();
- QTC_ASSERT(core, return false);
-
- Core::ActionManagerInterface *actionManager = core->actionManager();
+ Core::ActionManagerInterface *actionManager = m_core->actionManager();
QTC_ASSERT(actionManager, return false);
QList<int> globalcontext;
@@ -143,44 +142,33 @@ void FakeVimPlugin::extensionsInitialized()
void FakeVimPlugin::installHandler()
{
- ICore *core = m_pm->getObject<Core::ICore>();
- if (!core || !core->editorManager())
+ if (!m_core || !m_core->editorManager())
return;
- Core::IEditor *editor = core->editorManager()->currentEditor();
+ Core::IEditor *editor = m_core->editorManager()->currentEditor();
ITextEditor *textEditor = qobject_cast<ITextEditor*>(editor);
if (!textEditor)
return;
- QWidget *widget = textEditor->widget();
- QPlainTextEdit *plainTextEdit = qobject_cast<QPlainTextEdit *>(widget);
- if (!plainTextEdit)
- return;
- plainTextEdit->removeEventFilter(m_handler);
- plainTextEdit->installEventFilter(m_handler);
- QFont font = plainTextEdit->font();
- //font.setFamily("Monospace");
- m_savedCursorWidth = plainTextEdit->cursorWidth();
- plainTextEdit->setCursorWidth(QFontMetrics(font).width(QChar('x')));
-
- //QMainWindow mw;
connect(m_handler, SIGNAL(commandBufferChanged(QString)),
this, SLOT(showCommandBuffer(QString)));
connect(m_handler, SIGNAL(quitRequested(QWidget *)),
this, SLOT(removeHandler(QWidget *)));
+
+ m_handler->addWidget(textEditor->widget());
}
void FakeVimPlugin::removeHandler(QWidget *widget)
{
- widget->removeEventFilter(m_handler);
- QPlainTextEdit *plainTextEdit = qobject_cast<QPlainTextEdit *>(widget);
- if (!plainTextEdit)
- return;
- plainTextEdit->setCursorWidth(m_savedCursorWidth);
+ m_handler->removeWidget(widget);
+ Core::EditorManager::instance()->hideEditorInfoBar(
+ QLatin1String(Constants::MINI_BUFFER));
}
void FakeVimPlugin::showCommandBuffer(const QString &contents)
{
- //qDebug() << "CMD: " << contents;
+ Core::EditorManager::instance()->showEditorInfoBar(
+ QLatin1String(Constants::MINI_BUFFER), contents,
+ tr("Quit FakeVim"), m_handler, SLOT(quit()));
}
diff --git a/src/plugins/fakevim/fakevimplugin.h b/src/plugins/fakevim/fakevimplugin.h
index 6561e871b0..9025affcec 100644
--- a/src/plugins/fakevim/fakevimplugin.h
+++ b/src/plugins/fakevim/fakevimplugin.h
@@ -44,8 +44,21 @@ class QCursor;
class QAbstractItemView;
QT_END_NAMESPACE
-namespace Core { class IEditor; }
-namespace TextEditor { class ITextEditor; }
+
+namespace Core {
+
+class ICore;
+class IEditor;
+
+} // namespace Core
+
+
+namespace TextEditor {
+
+class ITextEditor;
+
+} // namespace TextEditor
+
namespace FakeVim {
namespace Internal {
@@ -72,9 +85,8 @@ private slots:
private:
FakeVimHandler *m_handler;
- ExtensionSystem::PluginManager *m_pm;
QAction *m_installHandlerAction;
- int m_savedCursorWidth;
+ Core::ICore *m_core;
};
} // namespace Internal
diff --git a/src/plugins/fakevim/handler.cpp b/src/plugins/fakevim/handler.cpp
index fd8734f211..2fba751042 100644
--- a/src/plugins/fakevim/handler.cpp
+++ b/src/plugins/fakevim/handler.cpp
@@ -46,19 +46,21 @@
#include <QtGui/QScrollBar>
#include <QtGui/QTextBlock>
#include <QtGui/QTextCursor>
+#include <QtGui/QTextDocumentFragment>
#include <QtGui/QTextEdit>
using namespace FakeVim::Internal;
-#define StartOfLine QTextCursor::StartOfLine
-#define EndOfLine QTextCursor::EndOfLine
-#define MoveAnchor QTextCursor::MoveAnchor
-#define KeepAnchor QTextCursor::KeepAnchor
-#define Up QTextCursor::Up
-#define Down QTextCursor::Down
-#define Right QTextCursor::Right
-#define Left QTextCursor::Left
+#define StartOfLine QTextCursor::StartOfLine
+#define EndOfLine QTextCursor::EndOfLine
+#define MoveAnchor QTextCursor::MoveAnchor
+#define KeepAnchor QTextCursor::KeepAnchor
+#define Up QTextCursor::Up
+#define Down QTextCursor::Down
+#define Right QTextCursor::Right
+#define Left QTextCursor::Left
+#define EndOfDocument QTextCursor::End
///////////////////////////////////////////////////////////////////////
@@ -68,7 +70,6 @@ using namespace FakeVim::Internal;
///////////////////////////////////////////////////////////////////////
#define EDITOR(s) (m_textedit ? m_textedit->s : m_plaintextedit->s)
-#define THE_EDITOR (m_textedit ? (QWidget*)m_textedit : (QWidget*)m_plaintextedit)
const int ParagraphSeparator = 0x00002029;
@@ -78,7 +79,9 @@ enum Mode
{
InsertMode,
CommandMode,
- ExMode
+ ExMode,
+ SearchForwardMode,
+ SearchBackwardMode,
};
enum SubMode
@@ -87,7 +90,7 @@ enum SubMode
RegisterSubMode,
ChangeSubMode,
DeleteSubMode,
- ZSubMode
+ ZSubMode,
};
enum SubSubMode
@@ -99,16 +102,46 @@ enum SubSubMode
TickSubSubMode // used for '
};
+enum VisualMode
+{
+ NoVisualMode,
+ VisualCharMode,
+ VisualLineMode,
+ VisualBlockMode,
+};
+
static const QString ConfigStartOfLine = "startofline";
static const QString ConfigOn = "on";
+struct EditOperation
+{
+ EditOperation() : m_position(-1), m_itemCount(0) {}
+ int m_position;
+ int m_itemCount; // used to combine several operations
+ QString m_from;
+ QString m_to;
+};
+
+QDebug &operator<<(QDebug &ts, const EditOperation &op)
+{
+ if (op.m_itemCount > 0) {
+ ts << "EDIT BLOCK WITH" << op.m_itemCount << "ITEMS";
+ } else {
+ ts << "EDIT AT " << op.m_position
+ << " FROM " << op.m_from << " TO " << op.m_to;
+ }
+ return ts;
+}
+
class FakeVimHandler::Private
{
public:
Private(FakeVimHandler *parent);
bool eventFilter(QObject *ob, QEvent *ev);
+ void handleExCommand(const QString &cmd);
+private:
static int shift(int key) { return key + 32; }
static int control(int key) { return key + 256; }
@@ -117,11 +150,9 @@ public:
void handleInsertMode(int key, const QString &text);
void handleCommandMode(int key, const QString &text);
void handleRegisterMode(int key, const QString &text);
- void handleExMode(int key, const QString &text);
- void finishMovement();
- void updateMiniBuffer();
+ void handleMiniBufferModes(int key, const QString &text);
+ void finishMovement(const QString &text = QString());
void search(const QString &needle, bool forward);
- void showMessage(const QString &msg);
int mvCount() const { return m_mvcount.isEmpty() ? 1 : m_mvcount.toInt(); }
int opCount() const { return m_opcount.isEmpty() ? 1 : m_opcount.toInt(); }
@@ -131,47 +162,57 @@ public:
bool atEol() const { return m_tc.atBlockEnd() && m_tc.block().length()>1; }
int lastPositionInDocument() const;
-
- // all zero-based counting
- int cursorLineOnScreen() const;
- int linesOnScreen() const;
- int columnsOnScreen() const;
- int cursorLineInDocument() const;
- int cursorColumnInDocument() const;
+ int positionForLine(int line) const; // 1 based line, 0 based pos
+ int lineForPosition(int pos) const; // 1 based line, 0 based pos
+
+ // all zero-based counting
+ int cursorLineOnScreen() const;
+ int linesOnScreen() const;
+ int columnsOnScreen() const;
+ int cursorLineInDocument() const;
+ int cursorColumnInDocument() const;
int linesInDocument() const;
- void scrollToLineInDocument(int line);
+ void scrollToLineInDocument(int line);
void moveToFirstNonBlankOnLine();
void moveToNextWord(bool simple);
void moveToWordBoundary(bool simple, bool forward);
void handleFfTt(int key);
- void handleCommand(const QString &cmd);
// helper function for handleCommand. return 1 based line index.
int readLineCode(QString &cmd);
+ QTextCursor selectRange(int beginLine, int endLine);
+public:
+ void enterInsertMode();
+ void enterCommandMode();
+ void showMessage(const QString &msg);
+ void updateMiniBuffer();
+ void updateSelection();
+ void quit();
+
+public:
+ QTextEdit *m_textedit;
+ QPlainTextEdit *m_plaintextedit;
+
+private:
FakeVimHandler *q;
Mode m_mode;
SubMode m_submode;
SubSubMode m_subsubmode;
int m_subsubdata;
QString m_input;
- QTextEdit *m_textedit;
- QPlainTextEdit *m_plaintextedit;
QTextCursor m_tc;
QHash<int, QString> m_registers;
int m_register;
QString m_mvcount;
QString m_opcount;
- QStack<QString> m_undoStack;
- QStack<QString> m_redoStack;
-
bool m_fakeEnd;
- bool isSearchCommand() const
- { return m_commandCode == '?' || m_commandCode == '/'; }
- int m_commandCode; // ?, /, : ...
+ QWidget *editor() const;
+ bool isSearchMode() const
+ { return m_mode == SearchForwardMode || m_mode == SearchBackwardMode; }
int m_gflag; // whether current command started with 'g'
QString m_commandBuffer;
@@ -181,15 +222,33 @@ public:
bool m_lastSearchForward;
QString m_lastInsertion;
- // History for '/'
+ // undo handling
+ void recordInsert(int position, const QString &data);
+ void recordRemove(int position, const QString &data);
+ void recordRemove(int position, int length);
+ void undo();
+ void redo();
+ QStack<EditOperation> m_undoStack;
+ QStack<EditOperation> m_redoStack;
+
+ // extra data for '.'
+ QString m_dotCount;
+ QString m_dotCommand;
+
+ // history for '/'
QString lastSearchString() const;
QStringList m_searchHistory;
int m_searchHistoryIndex;
- // History for ':'
+ // history for ':'
QStringList m_commandHistory;
int m_commandHistoryIndex;
+ // visual line mode
+ void enterVisualMode(VisualMode visualMode);
+ void leaveVisualMode();
+ VisualMode m_visualMode;
+
// marks as lines
QHash<int, int> m_marks;
@@ -204,13 +263,13 @@ FakeVimHandler::Private::Private(FakeVimHandler *parent)
m_mode = CommandMode;
m_submode = NoSubMode;
m_subsubmode = NoSubSubMode;
- m_commandCode = 0;
m_fakeEnd = false;
m_lastSearchForward = true;
m_register = '"';
m_gflag = false;
m_textedit = 0;
m_plaintextedit = 0;
+ m_visualMode = NoVisualMode;
m_config[ConfigStartOfLine] = ConfigOn;
}
@@ -254,22 +313,30 @@ bool FakeVimHandler::Private::eventFilter(QObject *ob, QEvent *ev)
void FakeVimHandler::Private::handleKey(int key, const QString &text)
{
+ //qDebug() << "KEY: " << key << text << "POS: " << m_tc.position();
+ //qDebug() << "\nUNDO: " << m_undoStack << "\nREDO: " << m_redoStack;
if (m_mode == InsertMode)
handleInsertMode(key, text);
else if (m_mode == CommandMode)
handleCommandMode(key, text);
- else if (m_mode == ExMode)
- handleExMode(key, text);
+ else if (m_mode == ExMode || m_mode == SearchForwardMode
+ || m_mode == SearchBackwardMode)
+ handleMiniBufferModes(key, text);
}
-void FakeVimHandler::Private::finishMovement()
+void FakeVimHandler::Private::finishMovement(const QString &dotCommand)
{
if (m_submode == ChangeSubMode) {
+ if (!dotCommand.isEmpty())
+ m_dotCommand = "c" + dotCommand;
m_registers[m_register] = m_tc.selectedText();
m_tc.removeSelectedText();
m_mode = InsertMode;
m_submode = NoSubMode;
} else if (m_submode == DeleteSubMode) {
+ if (!dotCommand.isEmpty())
+ m_dotCommand = "d" + dotCommand;
+ recordRemove(qMin(m_tc.position(), m_tc.anchor()), m_tc.selectedText());
m_registers[m_register] = m_tc.selectedText();
m_tc.removeSelectedText();
m_submode = NoSubMode;
@@ -281,18 +348,81 @@ void FakeVimHandler::Private::finishMovement()
m_gflag = false;
m_register = '"';
m_tc.clearSelection();
+
+ updateSelection();
updateMiniBuffer();
}
+void FakeVimHandler::Private::updateSelection()
+{
+ QList<QTextEdit::ExtraSelection> selections;
+ if (m_visualMode != NoVisualMode) {
+ QTextEdit::ExtraSelection sel;
+ sel.cursor = m_tc;
+ sel.format = m_tc.blockCharFormat();
+ sel.format.setFontWeight(QFont::Bold);
+ sel.format.setFontUnderline(true);
+ int cursorPos = m_tc.position();
+ int anchorPos = m_marks['<'];
+ //qDebug() << "POS: " << cursorPos << " ANCHOR: " << anchorPos;
+ if (m_visualMode == VisualCharMode) {
+ sel.cursor.setPosition(anchorPos, KeepAnchor);
+ selections.append(sel);
+ } else if (m_visualMode == VisualLineMode) {
+ sel.cursor.setPosition(qMin(cursorPos, anchorPos), MoveAnchor);
+ sel.cursor.movePosition(StartOfLine, MoveAnchor);
+ sel.cursor.setPosition(qMax(cursorPos, anchorPos), KeepAnchor);
+ sel.cursor.movePosition(EndOfLine, KeepAnchor);
+ selections.append(sel);
+ } else if (m_visualMode == VisualBlockMode) {
+ QTextCursor tc = m_tc;
+ tc.setPosition(anchorPos);
+ tc.movePosition(StartOfLine, MoveAnchor);
+ QTextBlock anchorBlock = tc.block();
+ QTextBlock cursorBlock = m_tc.block();
+ int anchorColumn = anchorPos - anchorBlock.position();
+ int cursorColumn = cursorPos - cursorBlock.position();
+ int startColumn = qMin(anchorColumn, cursorColumn);
+ int endColumn = qMax(anchorColumn, cursorColumn);
+ int endPos = cursorBlock.position();
+ while (tc.position() <= endPos) {
+ if (startColumn < tc.block().length() - 1) {
+ int last = qMin(tc.block().length() - 1, endColumn);
+ int len = last - startColumn + 1;
+ sel.cursor = tc;
+ sel.cursor.movePosition(Right, MoveAnchor, startColumn);
+ sel.cursor.movePosition(Right, KeepAnchor, len);
+ selections.append(sel);
+ }
+ tc.movePosition(Down, MoveAnchor, 1);
+ }
+ }
+ }
+ EDITOR(setExtraSelections(selections));
+}
+
void FakeVimHandler::Private::updateMiniBuffer()
{
- if (m_tc.isNull())
- return;
QString msg;
- if (m_currentMessage.isEmpty()) {
- msg = QChar(m_commandCode ? m_commandCode : ' ');
- for (int i = 0; i != m_commandBuffer.size(); ++i) {
- QChar c = m_commandBuffer.at(i);
+ if (!m_currentMessage.isEmpty()) {
+ msg = m_currentMessage;
+ m_currentMessage.clear();
+ } else if (m_visualMode == VisualCharMode) {
+ msg = "-- VISUAL --";
+ } else if (m_visualMode == VisualLineMode) {
+ msg = "-- VISUAL LINE --";
+ } else if (m_visualMode == VisualBlockMode) {
+ msg = "-- VISUAL BLOCK --";
+ } else if (m_mode == InsertMode) {
+ msg = "-- INSERT --";
+ } else {
+ if (m_mode == SearchForwardMode)
+ msg += '/';
+ else if (m_mode == SearchBackwardMode)
+ msg += '?';
+ else if (m_mode == ExMode)
+ msg += ':';
+ foreach (QChar c, m_commandBuffer) {
if (c.unicode() < 32) {
msg += '^';
msg += QChar(c.unicode() + 64);
@@ -300,20 +430,22 @@ void FakeVimHandler::Private::updateMiniBuffer()
msg += c;
}
}
- } else {
- msg = m_currentMessage;
- m_currentMessage.clear();
}
+ emit q->commandBufferChanged(msg);
+
+ int linesInDoc = linesInDocument();
int l = cursorLineInDocument();
- int w = columnsOnScreen();
- msg += QString(w, ' ');
- msg = msg.left(w - 20);
+ QString status;
QString pos = tr("%1,%2").arg(l + 1).arg(cursorColumnInDocument() + 1);
- msg += tr("%1").arg(pos, -12);
+ status += tr("%1").arg(pos, -10);
// FIXME: physical "-" logical
- msg += tr("%1").arg(l * 100 / (m_tc.document()->blockCount() - 1), 4);
- msg += '%';
- emit q->commandBufferChanged(msg);
+ if (linesInDoc != 0) {
+ status += tr("%1").arg(l * 100 / linesInDoc, 4);
+ status += "%";
+ } else {
+ status += "All";
+ }
+ emit q->statusDataChanged(status);
}
void FakeVimHandler::Private::showMessage(const QString &msg)
@@ -334,16 +466,16 @@ void FakeVimHandler::Private::handleCommandMode(int key, const QString &text)
m_tc.movePosition(StartOfLine, MoveAnchor);
m_tc.movePosition(Down, KeepAnchor, count());
m_registers[m_register] = m_tc.selectedText();
- finishMovement();
+ finishMovement("c");
} else if (m_submode == DeleteSubMode && key == 'd') {
m_tc.movePosition(StartOfLine, MoveAnchor);
m_tc.movePosition(Down, KeepAnchor, count());
m_registers[m_register] = m_tc.selectedText();
- finishMovement();
+ finishMovement("d");
} else if (m_submode == ZSubMode) {
if (key == Key_Return) {
// cursor line to top of window, cursor on first non-blank
- scrollToLineInDocument(cursorLineInDocument());
+ scrollToLineInDocument(cursorLineInDocument());
moveToFirstNonBlankOnLine();
finishMovement();
} else {
@@ -353,14 +485,14 @@ void FakeVimHandler::Private::handleCommandMode(int key, const QString &text)
} else if (m_subsubmode == FtSubSubMode) {
handleFfTt(key);
m_subsubmode = NoSubSubMode;
- finishMovement();
+ finishMovement(QString(QChar(m_subsubdata)) + QChar(key));
} else if (m_subsubmode == MarkSubSubMode) {
m_marks[key] = m_tc.position();
m_subsubmode = NoSubSubMode;
} else if (m_subsubmode == BackTickSubSubMode
|| m_subsubmode == TickSubSubMode) {
if (m_marks.contains(key)) {
- m_tc.setPosition(m_marks[key]);
+ m_tc.setPosition(m_marks[key], MoveAnchor);
if (m_subsubmode == TickSubSubMode)
moveToFirstNonBlankOnLine();
finishMovement();
@@ -375,16 +507,21 @@ void FakeVimHandler::Private::handleCommandMode(int key, const QString &text)
} else {
m_mvcount.append(QChar(key));
}
- } else if (key == ':' || key == '/' || key == '?') {
- m_commandCode = key;
+ } else if (key == ':') {
m_mode = ExMode;
- if (isSearchCommand()) {
- m_searchHistory.append(QString());
- m_searchHistoryIndex = m_searchHistory.size() - 1;
- } else {
- m_commandHistory.append(QString());
- m_commandHistoryIndex = m_commandHistory.size() - 1;
+ m_commandBuffer.clear();
+ if (m_visualMode != NoVisualMode) {
+ m_commandBuffer = "'<,'>";
+ leaveVisualMode();
}
+ m_commandHistory.append(QString());
+ m_commandHistoryIndex = m_commandHistory.size() - 1;
+ updateMiniBuffer();
+ } else if (key == '/' || key == '?') {
+ m_mode = (key == '/') ? SearchForwardMode : SearchBackwardMode;
+ m_commandBuffer.clear();
+ m_searchHistory.append(QString());
+ m_searchHistoryIndex = m_searchHistory.size() - 1;
updateMiniBuffer();
} else if (key == '`') {
m_subsubmode = BackTickSubSubMode;
@@ -405,14 +542,18 @@ void FakeVimHandler::Private::handleCommandMode(int key, const QString &text)
} else if (key == '$' || key == Key_End) {
m_tc.movePosition(EndOfLine, KeepAnchor);
finishMovement();
+ } else if (key == '.') {
+ qDebug() << "REPEATING" << m_dotCommand;
+ for (int i = count(); --i >= 0; )
+ foreach (QChar c, m_dotCommand)
+ handleKey(c.unicode(), QString(c));
} else if (key == 'a') {
m_mode = InsertMode;
m_lastInsertion.clear();
- m_tc.beginEditBlock();
m_tc.movePosition(Right, MoveAnchor, 1);
+ updateMiniBuffer();
} else if (key == 'A') {
m_mode = InsertMode;
- m_tc.beginEditBlock();
m_tc.movePosition(EndOfLine, MoveAnchor);
m_lastInsertion.clear();
} else if (key == 'b') {
@@ -423,18 +564,22 @@ void FakeVimHandler::Private::handleCommandMode(int key, const QString &text)
finishMovement();
} else if (key == 'c') {
m_submode = ChangeSubMode;
- m_tc.beginEditBlock();
} else if (key == 'C') {
m_submode = ChangeSubMode;
- m_tc.beginEditBlock();
m_tc.movePosition(EndOfLine, KeepAnchor);
finishMovement();
- } else if (key == 'd') {
+ } else if (key == 'd' && m_visualMode == NoVisualMode) {
if (atEol())
m_tc.movePosition(Left, MoveAnchor, 1);
m_opcount = m_mvcount;
m_mvcount.clear();
m_submode = DeleteSubMode;
+ } else if (key == 'd') {
+ leaveVisualMode();
+ int beginLine = lineForPosition(m_marks['<']);
+ int endLine = lineForPosition(m_marks['>']);
+ m_tc = selectRange(beginLine, endLine);
+ m_tc.removeSelectedText();
} else if (key == 'D') {
m_submode = DeleteSubMode;
m_tc.movePosition(Down, KeepAnchor, qMax(count() - 1, 0));
@@ -453,7 +598,7 @@ void FakeVimHandler::Private::handleCommandMode(int key, const QString &text)
m_gflag = true;
} else if (key == 'G') {
int n = m_mvcount.isEmpty() ? linesInDocument() : count();
- m_tc.setPosition(m_tc.document()->findBlockByNumber(n - 1).position());
+ m_tc.setPosition(positionForLine(n), MoveAnchor);
if (m_config.contains(ConfigStartOfLine))
moveToFirstNonBlankOnLine();
finishMovement();
@@ -469,23 +614,19 @@ void FakeVimHandler::Private::handleCommandMode(int key, const QString &text)
moveToFirstNonBlankOnLine();
finishMovement();
} else if (key == 'i') {
- m_mode = InsertMode;
- m_tc.beginEditBlock();
- m_lastInsertion.clear();
+ enterInsertMode();
+ updateMiniBuffer();
} else if (key == 'I') {
- m_mode = InsertMode;
+ enterInsertMode();
if (m_gflag)
m_tc.movePosition(StartOfLine, KeepAnchor);
else
moveToFirstNonBlankOnLine();
- m_tc.clearSelection();
- m_tc.beginEditBlock();
- m_lastInsertion.clear();
} else if (key == 'j' || key == Key_Down) {
m_tc.movePosition(Down, KeepAnchor, count());
finishMovement();
} else if (key == 'J') {
- m_tc.beginEditBlock();
+ EditOperation op;
if (m_submode == NoSubMode) {
for (int i = qMax(count(), 2) - 1; --i >= 0; ) {
m_tc.movePosition(EndOfLine);
@@ -496,7 +637,6 @@ void FakeVimHandler::Private::handleCommandMode(int key, const QString &text)
if (!m_gflag)
m_tc.movePosition(Left, MoveAnchor, 1);
}
- m_tc.endEditBlock();
} else if (key == 'k' || key == Key_Up) {
m_tc.movePosition(Up, KeepAnchor, count());
finishMovement();
@@ -519,15 +659,11 @@ void FakeVimHandler::Private::handleCommandMode(int key, const QString &text)
} else if (key == 'N') {
search(lastSearchString(), !m_lastSearchForward);
} else if (key == 'o') {
- m_mode = InsertMode;
- m_lastInsertion.clear();
- //m_tc.beginEditBlock(); // FIXME: unusable due to drawing errors
+ enterInsertMode();
m_tc.movePosition(EndOfLine, MoveAnchor);
m_tc.insertText("\n");
} else if (key == 'O') {
- m_mode = InsertMode;
- m_lastInsertion.clear();
- //m_tc.beginEditBlock(); // FIXME: unusable due to drawing errors
+ enterInsertMode();
m_tc.movePosition(StartOfLine, MoveAnchor);
m_tc.movePosition(Left, MoveAnchor, 1);
m_tc.insertText("\n");
@@ -545,29 +681,33 @@ void FakeVimHandler::Private::handleCommandMode(int key, const QString &text)
m_tc.movePosition(Left);
}
} else if (key == control('r')) {
- EDITOR(redo());
+ redo();
} else if (key == 's') {
m_submode = ChangeSubMode;
- m_tc.beginEditBlock();
m_tc.movePosition(Right, KeepAnchor, qMin(count(), rightDist()));
- finishMovement();
} else if (key == 't' || key == 'T') {
m_subsubmode = FtSubSubMode;
m_subsubdata = key;
} else if (key == 'u') {
- EDITOR(undo());
+ undo();
+ } else if (key == 'v') {
+ enterVisualMode(VisualCharMode);
+ } else if (key == 'V') {
+ enterVisualMode(VisualLineMode);
+ } else if (key == control('v')) {
+ enterVisualMode(VisualBlockMode);
} else if (key == 'w') {
moveToNextWord(false);
- finishMovement();
+ finishMovement("w");
} else if (key == 'W') {
moveToNextWord(true);
- finishMovement();
+ finishMovement("W");
} else if (key == 'x') { // = "dl"
if (atEol())
m_tc.movePosition(Left, MoveAnchor, 1);
m_submode = DeleteSubMode;
m_tc.movePosition(Right, KeepAnchor, qMin(count(), rightDist()));
- finishMovement();
+ finishMovement("l");
} else if (key == 'X') {
if (leftDist() > 0) {
m_tc.movePosition(Left, KeepAnchor, qMin(count(), leftDist()));
@@ -596,7 +736,8 @@ void FakeVimHandler::Private::handleCommandMode(int key, const QString &text)
} else if (key == Key_Delete) {
m_tc.deleteChar();
} else if (key == Key_Escape) {
- // harmless
+ if (m_visualMode != NoVisualMode)
+ leaveVisualMode();
} else {
qDebug() << "Ignored" << key << text;
}
@@ -605,11 +746,16 @@ void FakeVimHandler::Private::handleCommandMode(int key, const QString &text)
void FakeVimHandler::Private::handleInsertMode(int key, const QString &text)
{
if (key == Key_Escape) {
- for (int i = 1; i < count(); ++i)
+ // start with '1', as one instance was already physically inserted
+ // while typing
+ QString data = m_lastInsertion;
+ for (int i = 1; i < count(); ++i) {
m_tc.insertText(m_lastInsertion);
+ data += m_lastInsertion;
+ }
+ recordInsert(m_tc.position() - m_lastInsertion.size(), data);
m_tc.movePosition(Left, MoveAnchor, qMin(1, leftDist()));
- m_mode = CommandMode;
- m_tc.endEditBlock();
+ enterCommandMode();
} else if (key == Key_Left) {
m_tc.movePosition(Left, MoveAnchor, 1);
m_lastInsertion.clear();
@@ -624,7 +770,7 @@ void FakeVimHandler::Private::handleInsertMode(int key, const QString &text)
m_lastInsertion.clear();
} else if (key == Key_Return) {
m_tc.insertBlock();
- m_lastInsertion.clear();
+ m_lastInsertion += "\n";
} else if (key == Key_Backspace) {
m_tc.deletePreviousChar();
m_lastInsertion = m_lastInsertion.left(m_lastInsertion.size() - 1);
@@ -644,45 +790,40 @@ void FakeVimHandler::Private::handleInsertMode(int key, const QString &text)
} else {
m_lastInsertion.append(text);
m_tc.insertText(text);
- }
+ }
+ updateMiniBuffer();
}
-void FakeVimHandler::Private::handleExMode(int key, const QString &text)
+void FakeVimHandler::Private::handleMiniBufferModes(int key, const QString &text)
{
Q_UNUSED(text)
if (key == Key_Escape) {
m_commandBuffer.clear();
- m_commandCode = 0;
- m_mode = CommandMode;
+ enterCommandMode();
updateMiniBuffer();
} else if (key == Key_Backspace) {
if (m_commandBuffer.isEmpty())
- m_mode = CommandMode;
+ enterCommandMode();
else
m_commandBuffer.chop(1);
updateMiniBuffer();
- } else if (key == Key_Return && m_commandCode == ':') {
+ } else if (key == Key_Return && m_mode == ExMode) {
if (!m_commandBuffer.isEmpty()) {
m_commandHistory.takeLast();
m_commandHistory.append(m_commandBuffer);
- handleCommand(m_commandBuffer);
- m_commandBuffer.clear();
- m_commandCode = 0;
+ handleExCommand(m_commandBuffer);
}
- m_mode = CommandMode;
- } else if (key == Key_Return && isSearchCommand()) {
+ } else if (key == Key_Return && isSearchMode()) {
if (!m_commandBuffer.isEmpty()) {
m_searchHistory.takeLast();
m_searchHistory.append(m_commandBuffer);
- m_lastSearchForward = (m_commandCode == '/');
+ m_lastSearchForward = (m_mode == SearchForwardMode);
search(lastSearchString(), m_lastSearchForward);
- m_commandBuffer.clear();
- m_commandCode = 0;
}
- m_mode = CommandMode;
+ enterCommandMode();
updateMiniBuffer();
- } else if (key == Key_Up && isSearchCommand()) {
+ } else if (key == Key_Up && isSearchMode()) {
// FIXME: This and the three cases below are wrong as vim
// takes only matching entires in the history into account.
if (m_searchHistoryIndex > 0) {
@@ -690,19 +831,19 @@ void FakeVimHandler::Private::handleExMode(int key, const QString &text)
m_commandBuffer = m_searchHistory.at(m_searchHistoryIndex);
updateMiniBuffer();
}
- } else if (key == Key_Up && m_commandCode == ':') {
+ } else if (key == Key_Up && m_mode == ExMode) {
if (m_commandHistoryIndex > 0) {
--m_commandHistoryIndex;
m_commandBuffer = m_commandHistory.at(m_commandHistoryIndex);
updateMiniBuffer();
}
- } else if (key == Key_Down && isSearchCommand()) {
+ } else if (key == Key_Down && isSearchMode()) {
if (m_searchHistoryIndex < m_searchHistory.size() - 1) {
++m_searchHistoryIndex;
m_commandBuffer = m_searchHistory.at(m_searchHistoryIndex);
updateMiniBuffer();
}
- } else if (key == Key_Down && m_commandCode == ':') {
+ } else if (key == Key_Down && m_mode == ExMode) {
if (m_commandHistoryIndex < m_commandHistory.size() - 1) {
++m_commandHistoryIndex;
m_commandBuffer = m_commandHistory.at(m_commandHistoryIndex);
@@ -737,6 +878,16 @@ int FakeVimHandler::Private::readLineCode(QString &cmd)
int n = readLineCode(cmd);
return cursorLineInDocument() + 1 + (n == -1 ? 1 : n);
}
+ if (c == '\'' && !cmd.isEmpty()) {
+ int pos = m_marks.value(cmd.at(0).unicode());
+ qDebug() << " MARK: " << cmd.at(0) << pos << lineForPosition(pos);
+ if (!pos) {
+ showMessage(tr("E20: Mark '%1' not set").arg(cmd.at(0)));
+ return -1;
+ }
+ cmd = cmd.mid(1);
+ return lineForPosition(pos);
+ }
if (c.isDigit()) {
int n = c.unicode() - '0';
while (!cmd.isEmpty()) {
@@ -754,14 +905,27 @@ int FakeVimHandler::Private::readLineCode(QString &cmd)
return -1;
}
-void FakeVimHandler::Private::handleCommand(const QString &cmd0)
+QTextCursor FakeVimHandler::Private::selectRange(int beginLine, int endLine)
+{
+ QTextCursor tc = m_tc;
+ tc.setPosition(positionForLine(beginLine), MoveAnchor);
+ if (endLine == linesInDocument()) {
+ tc.setPosition(positionForLine(endLine), KeepAnchor);
+ tc.movePosition(EndOfLine, KeepAnchor);
+ } else {
+ tc.setPosition(positionForLine(endLine + 1), KeepAnchor);
+ }
+ return tc;
+}
+
+void FakeVimHandler::Private::handleExCommand(const QString &cmd0)
{
QString cmd = cmd0;
if (cmd.startsWith("%"))
cmd = "1,$" + cmd.mid(1);
- int beginLine = 0;
- int endLine = linesInDocument();
+ int beginLine = -1;
+ int endLine = -1;
int line = readLineCode(cmd);
if (line != -1)
@@ -774,44 +938,68 @@ void FakeVimHandler::Private::handleCommand(const QString &cmd0)
endLine = line;
}
- //qDebug() << "RANGE: " << beginLine << endLine << cmd << cmd0;
+ qDebug() << "RANGE: " << beginLine << endLine << cmd << cmd0;
static QRegExp reWrite("^w!?( (.*))?$");
+ static QRegExp reDelete("^d( (.*))?$");
if (cmd.isEmpty()) {
- m_tc.setPosition(m_tc.block().document()
- ->findBlockByNumber(beginLine - 1).position());
- showMessage(QString());
- } else if (cmd == "q!" || cmd == "q") {
- q->quitRequested(THE_EDITOR);
+ m_tc.setPosition(positionForLine(beginLine));
showMessage(QString());
- } else if (reWrite.indexIn(cmd) != -1) {
+ } else if (cmd == "q!" || cmd == "q") { // :q
+ quit();
+ } else if (reDelete.indexIn(cmd) != -1) { // :d
+ if (beginLine == -1)
+ beginLine = cursorLineInDocument();
+ if (endLine == -1)
+ endLine = cursorLineInDocument();
+ QTextCursor tc = selectRange(beginLine, endLine);
+ QString reg = reDelete.cap(2);
+ if (!reg.isEmpty())
+ m_registers[reg.at(0).unicode()] = tc.selection().toPlainText();
+ tc.removeSelectedText();
+ } else if (reWrite.indexIn(cmd) != -1) { // :w
+ enterCommandMode();
+ bool noArgs = (beginLine == -1);
+ if (beginLine == -1)
+ beginLine = 0;
+ if (endLine == -1)
+ endLine = linesInDocument();
+ qDebug() << "LINES: " << beginLine << endLine;
bool forced = cmd.startsWith("w!");
QString fileName = reWrite.cap(2);
if (fileName.isEmpty())
fileName = m_currentFileName;
QFile file(fileName);
bool exists = file.exists();
- if (exists && !forced) {
- showMessage("E13: File exists (add ! to override)");
- } else {
- file.open(QIODevice::ReadWrite);
- QTextStream ts(&file);
- ts << EDITOR(toPlainText());
+ if (exists && !forced && !noArgs) {
+ showMessage(tr("File '%1' exists (add ! to override)").arg(fileName));
+ } else if (file.open(QIODevice::ReadWrite)) {
+ QTextCursor tc = selectRange(beginLine, endLine);
+ qDebug() << "ANCHOR: " << tc.position() << tc.anchor()
+ << tc.selection().toPlainText();
+ { QTextStream ts(&file); ts << tc.selection().toPlainText(); }
file.close();
- file.open(QIODevice::ReadWrite);
+ file.open(QIODevice::ReadOnly);
QByteArray ba = file.readAll();
- showMessage(tr("\"%1\" %2 %3L, %4C written")
+ m_commandBuffer = QString("\"%1\" %2 %3L, %4C written")
.arg(fileName).arg(exists ? " " : " [New] ")
- .arg(ba.count('\n')).arg(ba.size()));
+ .arg(ba.count('\n')).arg(ba.size());
+ updateMiniBuffer();
+ } else {
+ showMessage(tr("Cannot open file '%1' for reading").arg(fileName));
}
- } else if (cmd.startsWith("r ")) {
+ } else if (cmd.startsWith("r ")) { // :r
m_currentFileName = cmd.mid(2);
QFile file(m_currentFileName);
file.open(QIODevice::ReadOnly);
QTextStream ts(&file);
- EDITOR(setPlainText(ts.readAll()));
- showMessage(QString());
+ QString data = ts.readAll();
+ EDITOR(setPlainText(data));
+ m_commandBuffer = QString("\"%1\" %2L, %3C")
+ .arg(m_currentFileName).arg(data.count('\n')).arg(data.size());
+ enterCommandMode();
+ updateMiniBuffer();
} else {
showMessage("E492: Not an editor command: " + cmd0);
}
@@ -961,30 +1149,37 @@ void FakeVimHandler::Private::moveToNextWord(bool simple)
int FakeVimHandler::Private::cursorLineOnScreen() const
{
- QRect rect = EDITOR(cursorRect());
- return rect.y() / rect.height();
+ if (!editor())
+ return 0;
+ QRect rect = EDITOR(cursorRect());
+ return rect.y() / rect.height();
}
int FakeVimHandler::Private::linesOnScreen() const
{
- QRect rect = EDITOR(cursorRect());
- return EDITOR(height()) / rect.height();
+ if (!editor())
+ return 1;
+ QRect rect = EDITOR(cursorRect());
+ return EDITOR(height()) / rect.height();
}
int FakeVimHandler::Private::columnsOnScreen() const
{
- QRect rect = EDITOR(cursorRect());
- return EDITOR(width()) / rect.width();
+ if (!editor())
+ return 1;
+ QRect rect = EDITOR(cursorRect());
+ // qDebug() << "WID: " << EDITOR(width()) << "RECT: " << rect;
+ return EDITOR(width()) / rect.width();
}
int FakeVimHandler::Private::cursorLineInDocument() const
{
- return m_tc.block().blockNumber();
+ return m_tc.block().blockNumber();
}
int FakeVimHandler::Private::cursorColumnInDocument() const
{
- return m_tc.position() - m_tc.block().position();
+ return m_tc.position() - m_tc.block().position();
}
int FakeVimHandler::Private::linesInDocument() const
@@ -994,9 +1189,9 @@ int FakeVimHandler::Private::linesInDocument() const
void FakeVimHandler::Private::scrollToLineInDocument(int line)
{
- // FIXME: works only for QPlainTextEdit
- QScrollBar *scrollBar = EDITOR(verticalScrollBar());
- scrollBar->setValue(line);
+ // FIXME: works only for QPlainTextEdit
+ QScrollBar *scrollBar = EDITOR(verticalScrollBar());
+ scrollBar->setValue(line);
}
int FakeVimHandler::Private::lastPositionInDocument() const
@@ -1010,6 +1205,141 @@ QString FakeVimHandler::Private::lastSearchString() const
return m_searchHistory.empty() ? QString() : m_searchHistory.back();
}
+int FakeVimHandler::Private::positionForLine(int line) const
+{
+ return m_tc.block().document()->findBlockByNumber(line - 1).position();
+}
+
+int FakeVimHandler::Private::lineForPosition(int pos) const
+{
+ QTextCursor tc = m_tc;
+ tc.setPosition(pos);
+ return tc.block().blockNumber() + 1;
+}
+
+void FakeVimHandler::Private::enterVisualMode(VisualMode visualMode)
+{
+ m_visualMode = visualMode;
+ m_marks['<'] = m_tc.position();
+ updateMiniBuffer();
+ updateSelection();
+}
+
+void FakeVimHandler::Private::leaveVisualMode()
+{
+ m_visualMode = NoVisualMode;
+ m_marks['>'] = m_tc.position();
+ updateMiniBuffer();
+ updateSelection();
+}
+
+QWidget *FakeVimHandler::Private::editor() const
+{
+ return m_textedit
+ ? static_cast<QWidget *>(m_textedit)
+ : static_cast<QWidget *>(m_plaintextedit);
+}
+
+void FakeVimHandler::Private::undo()
+{
+#if 0
+ EDITOR(undo());
+#else
+ if (m_undoStack.isEmpty())
+ return;
+ EditOperation op = m_undoStack.pop();
+ //qDebug() << "UNDO " << op;
+ if (op.m_itemCount > 0) {
+ for (int i = op.m_itemCount; --i >= 0; )
+ undo();
+ } else {
+ m_tc.setPosition(op.m_position, MoveAnchor);
+ if (!op.m_to.isEmpty()) {
+ m_tc.setPosition(op.m_position + op.m_to.size(), KeepAnchor);
+ m_tc.deleteChar();
+ }
+ if (!op.m_from.isEmpty())
+ m_tc.insertText(op.m_from);
+ m_tc.setPosition(op.m_position, MoveAnchor);
+ }
+ m_redoStack.push(op);
+#endif
+}
+
+void FakeVimHandler::Private::redo()
+{
+#if 0
+ EDITOR(redo());
+#else
+ if (m_redoStack.isEmpty())
+ return;
+ EditOperation op = m_redoStack.pop();
+ //qDebug() << "REDO " << op;
+ if (op.m_itemCount > 0) {
+ for (int i = op.m_itemCount; --i >= 0; )
+ redo();
+ } else {
+ m_tc.setPosition(op.m_position, MoveAnchor);
+ if (!op.m_from.isEmpty()) {
+ m_tc.setPosition(op.m_position + op.m_from.size(), KeepAnchor);
+ m_tc.deleteChar();
+ }
+ if (!op.m_to.isEmpty())
+ m_tc.insertText(op.m_to);
+ m_tc.setPosition(op.m_position, MoveAnchor);
+ }
+ m_undoStack.push(op);
+#endif
+}
+
+void FakeVimHandler::Private::recordInsert(int position, const QString &data)
+{
+ EditOperation op;
+ op.m_position = position;
+ op.m_to = data;
+ m_undoStack.push(op);
+ m_redoStack.clear();
+}
+
+void FakeVimHandler::Private::recordRemove(int position, int length)
+{
+ QTextCursor tc = m_tc;
+ tc.setPosition(position, MoveAnchor);
+ tc.setPosition(position + length, KeepAnchor);
+ recordRemove(position, tc.selection().toPlainText());
+}
+
+void FakeVimHandler::Private::recordRemove(int position, const QString &data)
+{
+ EditOperation op;
+ op.m_position = position;
+ op.m_from = data;
+ m_undoStack.push(op);
+ m_redoStack.clear();
+}
+
+void FakeVimHandler::Private::enterInsertMode()
+{
+ EDITOR(setOverwriteMode(false));
+ m_mode = InsertMode;
+ m_lastInsertion.clear();
+}
+
+void FakeVimHandler::Private::enterCommandMode()
+{
+ if (editor())
+ EDITOR(setOverwriteMode(true));
+ m_mode = CommandMode;
+}
+
+void FakeVimHandler::Private::quit()
+{
+ showMessage(QString());
+ EDITOR(setOverwriteMode(false));
+ q->quitRequested(editor());
+}
+
+
///////////////////////////////////////////////////////////////////////
//
// FakeVimHandler
@@ -1035,23 +1365,22 @@ bool FakeVimHandler::eventFilter(QObject *ob, QEvent *ev)
void FakeVimHandler::addWidget(QWidget *widget)
{
widget->installEventFilter(this);
- QFont font = widget->font();
- //: -misc-fixed-medium-r-semicondensed--13-120-75-75-c-60-iso8859-1
- //font.setFamily("Misc");
- font.setFamily("Monospace");
- font.setStretch(QFont::SemiCondensed);
- widget->setFont(font);
+ d->enterCommandMode();
if (QTextEdit *ed = qobject_cast<QTextEdit *>(widget)) {
- ed->setCursorWidth(QFontMetrics(ed->font()).width(QChar('x')));
+ //ed->setCursorWidth(QFontMetrics(ed->font()).width(QChar('x')));
ed->setLineWrapMode(QTextEdit::NoWrap);
} else if (QPlainTextEdit *ed = qobject_cast<QPlainTextEdit *>(widget)) {
- ed->setCursorWidth(QFontMetrics(ed->font()).width(QChar('x')));
+ //ed->setCursorWidth(QFontMetrics(ed->font()).width(QChar('x')));
ed->setLineWrapMode(QPlainTextEdit::NoWrap);
}
+ d->showMessage("vi emulation mode. Hit <Shift+Esc>:q<Return> to quit");
+ d->updateMiniBuffer();
}
void FakeVimHandler::removeWidget(QWidget *widget)
{
+ d->showMessage(QString());
+ d->updateMiniBuffer();
widget->removeEventFilter(this);
}
@@ -1059,6 +1388,11 @@ void FakeVimHandler::handleCommand(QWidget *widget, const QString &cmd)
{
d->m_textedit = qobject_cast<QTextEdit *>(widget);
d->m_plaintextedit = qobject_cast<QPlainTextEdit *>(widget);
- d->handleCommand(cmd);
+ d->handleExCommand(cmd);
}
+
+void FakeVimHandler::quit()
+{
+ d->quit();
+}
diff --git a/src/plugins/fakevim/handler.h b/src/plugins/fakevim/handler.h
index 1ebf9adb8e..fccb9f0f84 100644
--- a/src/plugins/fakevim/handler.h
+++ b/src/plugins/fakevim/handler.h
@@ -52,16 +52,20 @@ public:
FakeVimHandler(QObject *parent = 0);
~FakeVimHandler();
+public slots:
// The same handler can be installed on several widgets
+ // FIXME: good idea?
void addWidget(QWidget *widget);
void removeWidget(QWidget *widget);
// This executes an "ex" style command taking context
// information from \p widget;
void handleCommand(QWidget *widget, const QString &cmd);
+ void quit();
signals:
void commandBufferChanged(const QString &msg);
+ void statusDataChanged(const QString &msg);
void quitRequested(QWidget *);
private:
diff --git a/src/plugins/find/currentdocumentfind.cpp b/src/plugins/find/currentdocumentfind.cpp
index 26ed8dd049..dd25564a43 100644
--- a/src/plugins/find/currentdocumentfind.cpp
+++ b/src/plugins/find/currentdocumentfind.cpp
@@ -147,9 +147,11 @@ void CurrentDocumentFind::updateCurrentFindFilter(QWidget *old, QWidget *now)
if (!impl)
candidate = candidate->parentWidget();
}
- if (!impl)
+ if (!impl || impl == m_currentFind)
return;
removeFindSupportConnections();
+ if (m_currentFind)
+ m_currentFind->highlightAll(QString(), 0);
m_currentWidget = candidate;
m_currentFind = impl;
if (m_currentFind) {
diff --git a/src/plugins/git/branchdialog.cpp b/src/plugins/git/branchdialog.cpp
index 8d06c871f9..3eeee2347b 100644
--- a/src/plugins/git/branchdialog.cpp
+++ b/src/plugins/git/branchdialog.cpp
@@ -58,8 +58,9 @@ bool BranchDialog::init(GitClient *client, const QString &workingDirectory, QStr
}
m_ui->repositoryFieldLabel->setText(m_repoDirectory);
- m_localModel = new BranchModel(client, BranchModel::LocalBranches, this);
- m_remoteModel = new BranchModel(client, BranchModel::RemoteBranches, this);
+ m_localModel = new LocalBranchModel(client, this);
+ connect(m_localModel, SIGNAL(newBranchCreated(QString)), this, SLOT(slotNewLocalBranchCreated(QString)));
+ m_remoteModel = new RemoteBranchModel(client, this);
if (!m_localModel->refresh(workingDirectory, errorMessage)
|| !m_remoteModel->refresh(workingDirectory, errorMessage))
return false;
@@ -93,13 +94,23 @@ void BranchDialog::slotEnableButtons()
const int selectedLocalRow = selectedLocalBranchIndex();
const int currentLocalBranch = m_localModel->currentBranch();
- const bool hasSelection = selectedLocalRow != -1;
+ const bool hasSelection = selectedLocalRow != -1 && !m_localModel->isNewBranchRow(selectedLocalRow);
const bool currentIsNotSelected = hasSelection && selectedLocalRow != currentLocalBranch;
m_checkoutButton->setEnabled(currentIsNotSelected);
m_deleteButton->setEnabled(currentIsNotSelected);
}
+void BranchDialog::slotNewLocalBranchCreated(const QString &b)
+{
+ // Select the newly created branch
+ const int row = m_localModel->findBranchByName(b);
+ if (row != -1) {
+ const QModelIndex index = m_localModel->index(row);
+ m_ui->localBranchListView->selectionModel()->select(index, QItemSelectionModel::Select);
+ }
+}
+
bool BranchDialog::ask(const QString &title, const QString &what, bool defaultButton)
{
return QMessageBox::question(this, title, what, QMessageBox::Yes|QMessageBox::No,
diff --git a/src/plugins/git/branchdialog.h b/src/plugins/git/branchdialog.h
index 064719b8ff..c803b57e83 100644
--- a/src/plugins/git/branchdialog.h
+++ b/src/plugins/git/branchdialog.h
@@ -14,7 +14,8 @@ namespace Git {
}
class GitClient;
- class BranchModel;
+ class LocalBranchModel;
+ class RemoteBranchModel;
/* Branch dialog: Display a list of local branches at the top
* and remote branches below. Offers to checkout/delete local
@@ -39,6 +40,7 @@ namespace Git {
void slotCheckoutSelectedBranch();
void slotDeleteSelectedBranch();
void slotLocalBranchActivated();
+ void slotNewLocalBranchCreated(const QString &);
private:
bool ask(const QString &title, const QString &what, bool defaultButton);
@@ -51,8 +53,8 @@ namespace Git {
QPushButton *m_checkoutButton;
QPushButton *m_deleteButton;
- BranchModel *m_localModel;
- BranchModel *m_remoteModel;
+ LocalBranchModel *m_localModel;
+ RemoteBranchModel *m_remoteModel;
QString m_repoDirectory;
};
} // namespace Internal
diff --git a/src/plugins/git/branchmodel.cpp b/src/plugins/git/branchmodel.cpp
index b02d58dbd0..bb8ccf1951 100644
--- a/src/plugins/git/branchmodel.cpp
+++ b/src/plugins/git/branchmodel.cpp
@@ -2,6 +2,8 @@
#include "gitclient.h"
#include <QtCore/QDebug>
+#include <QtCore/QRegExp>
+#include <QtCore/QTimer>
enum { debug = 0 };
@@ -10,7 +12,7 @@ namespace Git {
// Parse a branch line: " *name sha description". Return true if it is
// the current one
-bool BranchModel::Branch::parse(const QString &lineIn, bool *isCurrent)
+bool RemoteBranchModel::Branch::parse(const QString &lineIn, bool *isCurrent)
{
if (debug)
qDebug() << Q_FUNC_INFO << lineIn;
@@ -28,40 +30,41 @@ bool BranchModel::Branch::parse(const QString &lineIn, bool *isCurrent)
return true;
}
-static inline Qt::ItemFlags typeToModelFlags(BranchModel::Type t)
+// ------ RemoteBranchModel
+RemoteBranchModel::RemoteBranchModel(GitClient *client, QObject *parent) :
+ QAbstractListModel(parent),
+ m_flags(Qt::ItemIsSelectable|Qt::ItemIsEnabled),
+ m_client(client)
{
- Qt::ItemFlags rc = Qt::ItemIsSelectable|Qt::ItemIsEnabled;
- if (t == BranchModel::LocalBranches)
- rc |= Qt::ItemIsUserCheckable;
- return rc;
}
-// --- BranchModel
-BranchModel::BranchModel(GitClient *client, Type type, QObject *parent) :
- QAbstractListModel(parent),
- m_type(type),
- m_flags(typeToModelFlags(type)),
- m_client(client),
- m_currentBranch(-1)
+bool RemoteBranchModel::refresh(const QString &workingDirectory, QString *errorMessage)
{
+ int currentBranch;
+ return refreshBranches(workingDirectory, true, &currentBranch, errorMessage);
}
-int BranchModel::currentBranch() const
+QString RemoteBranchModel::branchName(int row) const
{
- return m_currentBranch;
+ return m_branches.at(row).name;
}
-QString BranchModel::branchName(int row) const
+QString RemoteBranchModel::workingDirectory() const
{
- return m_branches.at(row).name;
+ return m_workingDirectory;
}
-int BranchModel::rowCount(const QModelIndex & /* parent */) const
+int RemoteBranchModel::branchCount() const
{
return m_branches.size();
}
-QVariant BranchModel::data(const QModelIndex &index, int role) const
+int RemoteBranchModel::rowCount(const QModelIndex & /* parent */) const
+{
+ return branchCount();
+}
+
+QVariant RemoteBranchModel::data(const QModelIndex &index, int role) const
{
const int row = index.row();
switch (role) {
@@ -72,36 +75,52 @@ QVariant BranchModel::data(const QModelIndex &index, int role) const
m_branches.at(row).toolTip = toolTip(m_branches.at(row).currentSHA);
return m_branches.at(row).toolTip;
break;
- case Qt::CheckStateRole:
- if (m_type == RemoteBranches)
- return QVariant();
- return row == m_currentBranch ? Qt::Checked : Qt::Unchecked;
default:
break;
}
return QVariant();
}
-Qt::ItemFlags BranchModel::flags(const QModelIndex & /*index */) const
+Qt::ItemFlags RemoteBranchModel::flags(const QModelIndex & /* index */) const
{
return m_flags;
}
-bool BranchModel::refresh(const QString &workingDirectory, QString *errorMessage)
+QString RemoteBranchModel::toolTip(const QString &sha) const
+{
+ // Show the sha description excluding diff as toolTip
+ QString output;
+ QString errorMessage;
+ if (!m_client->synchronousShow(m_workingDirectory, sha, &output, &errorMessage))
+ return errorMessage;
+ // Remove 'diff' output
+ const int diffPos = output.indexOf(QLatin1String("\ndiff --"));
+ if (diffPos != -1)
+ output.remove(diffPos, output.size() - diffPos);
+ return output;
+}
+
+bool RemoteBranchModel::runGitBranchCommand(const QString &workingDirectory, const QStringList &additionalArgs, QString *output, QString *errorMessage)
+{
+ return m_client->synchronousBranchCmd(workingDirectory, additionalArgs, output, errorMessage);
+}
+
+bool RemoteBranchModel::refreshBranches(const QString &workingDirectory, bool remoteBranches,
+ int *currentBranch, QString *errorMessage)
{
// Run branch command with verbose.
QStringList branchArgs(QLatin1String("-v"));
QString output;
- if (m_type == RemoteBranches)
+ *currentBranch = -1;
+ if (remoteBranches)
branchArgs.push_back(QLatin1String("-r"));
- if (!m_client->synchronousBranchCmd(workingDirectory, branchArgs, &output, errorMessage))
+ if (!runGitBranchCommand(workingDirectory, branchArgs, &output, errorMessage))
return false;
if (debug)
qDebug() << Q_FUNC_INFO << workingDirectory << output;
// Parse output
m_workingDirectory = workingDirectory;
m_branches.clear();
- m_currentBranch = -1;
const QStringList branches = output.split(QLatin1Char('\n'));
const int branchCount = branches.size();
bool isCurrent;
@@ -110,25 +129,122 @@ bool BranchModel::refresh(const QString &workingDirectory, QString *errorMessage
if (newBranch.parse(branches.at(b), &isCurrent)) {
m_branches.push_back(newBranch);
if (isCurrent)
- m_currentBranch = b;
+ *currentBranch = b;
}
}
reset();
return true;
}
-QString BranchModel::toolTip(const QString &sha) const
+int RemoteBranchModel::findBranchByName(const QString &name) const
{
- // Show the sha description excluding diff as toolTip
+ const int count = branchCount();
+ for (int i = 0; i < count; i++)
+ if (branchName(i) == name)
+ return i;
+ return -1;
+}
+
+// --- LocalBranchModel
+LocalBranchModel::LocalBranchModel(GitClient *client, QObject *parent) :
+ RemoteBranchModel(client, parent),
+ m_typeHere(tr("<New branch>")),
+ m_typeHereToolTip(tr("Type to create a new branch")),
+ m_currentBranch(-1)
+{
+}
+
+int LocalBranchModel::currentBranch() const
+{
+ return m_currentBranch;
+}
+
+bool LocalBranchModel::isNewBranchRow(int row) const
+{
+ return row >= branchCount();
+}
+
+Qt::ItemFlags LocalBranchModel::flags(const QModelIndex & index) const
+{
+ if (isNewBranchRow(index))
+ return Qt::ItemIsEditable|Qt::ItemIsSelectable|Qt::ItemIsEnabled| Qt::ItemIsUserCheckable;
+ return RemoteBranchModel::flags(index) | Qt::ItemIsUserCheckable;
+}
+
+int LocalBranchModel::rowCount(const QModelIndex & /* parent */) const
+{
+ return branchCount() + 1;
+}
+
+QVariant LocalBranchModel::data(const QModelIndex &index, int role) const
+{
+ if (isNewBranchRow(index)) {
+ switch (role) {
+ case Qt::DisplayRole:
+ return m_typeHere;
+ case Qt::ToolTipRole:
+ return m_typeHereToolTip;
+ case Qt::CheckStateRole:
+ return QVariant(false);
+ }
+ return QVariant();
+ }
+
+ if (role == Qt::CheckStateRole)
+ return index.row() == m_currentBranch ? Qt::Checked : Qt::Unchecked;
+ return RemoteBranchModel::data(index, role);
+}
+
+bool LocalBranchModel::refresh(const QString &workingDirectory, QString *errorMessage)
+{
+ return refreshBranches(workingDirectory, false, &m_currentBranch, errorMessage);
+}
+
+bool LocalBranchModel::checkNewBranchName(const QString &name) const
+{
+ // Syntax
+ const QRegExp pattern(QLatin1String("[a-zA-Z0-9-_]+"));
+ if (!pattern.exactMatch(name))
+ return false;
+ // existing
+ if (findBranchByName(name) != -1)
+ return false;
+ return true;
+}
+
+bool LocalBranchModel::setData(const QModelIndex &index, const QVariant &value, int role)
+{
+ // Verify
+ if (role != Qt::EditRole || index.row() < branchCount())
+ return false;
+ const QString branchName = value.toString();
+ const bool ok = checkNewBranchName(branchName);
+ if (debug)
+ qDebug() << Q_FUNC_INFO << branchName << ok;
+ if (!ok)
+ return false;
+ // Create
QString output;
QString errorMessage;
- if (!m_client->synchronousShow(m_workingDirectory, sha, &output, &errorMessage))
- return errorMessage;
- // Remove 'diff' output
- const int diffPos = output.indexOf(QLatin1String("\ndiff --"));
- if (diffPos != -1)
- output.remove(diffPos, output.size() - diffPos);
- return output;
+ if (!runGitBranchCommand(workingDirectory(), QStringList(branchName), &output, &errorMessage))
+ return false;
+ m_newBranch = branchName;
+ // Start a delayed complete refresh and return true for now.
+ QTimer::singleShot(0, this, SLOT(slotNewBranchDelayedRefresh()));
+ return true;
+}
+
+void LocalBranchModel::slotNewBranchDelayedRefresh()
+{
+ if (debug)
+ qDebug() << Q_FUNC_INFO;
+
+ QString errorMessage;
+ if (!refresh(workingDirectory(), &errorMessage)) {
+ qWarning("%s", qPrintable(errorMessage));
+ return;
+ }
+ emit newBranchCreated(m_newBranch);
}
}
diff --git a/src/plugins/git/branchmodel.h b/src/plugins/git/branchmodel.h
index 5083a1c377..91b1ca84dc 100644
--- a/src/plugins/git/branchmodel.h
+++ b/src/plugins/git/branchmodel.h
@@ -3,27 +3,25 @@
#include <QtCore/QAbstractListModel>
#include <QtCore/QList>
+#include <QtCore/QVariant>
namespace Git {
namespace Internal {
class GitClient;
-/* A model to list git branches in a simple list of branch names. Local
- * branches will have a read-only checkbox indicating the current one. The
- * [delayed] tooltip describes the latest commit. */
+/* A read-only model to list git remote branches in a simple list of branch names.
+ * The tooltip describes the latest commit (delayed creation).
+ * Provides virtuals to be able to derive a local branch model with the notion
+ * of a "current branch". */
-class BranchModel : public QAbstractListModel {
+class RemoteBranchModel : public QAbstractListModel {
+ Q_OBJECT
public:
- enum Type { LocalBranches, RemoteBranches };
+ explicit RemoteBranchModel(GitClient *client, QObject *parent = 0);
- explicit BranchModel(GitClient *client,
- Type type = LocalBranches,
- QObject *parent = 0);
-
- bool refresh(const QString &workingDirectory, QString *errorMessage);
+ virtual bool refresh(const QString &workingDirectory, QString *errorMessage);
- int currentBranch() const;
QString branchName(int row) const;
// QAbstractListModel
@@ -31,9 +29,12 @@ public:
virtual QVariant data(const QModelIndex &index, int role = Qt::DisplayRole) const;
virtual Qt::ItemFlags flags(const QModelIndex &index) const;
-private:
- QString toolTip(const QString &sha) const;
+ int branchCount() const;
+ QString workingDirectory() const;
+ int findBranchByName(const QString &name) const;
+
+protected:
struct Branch {
bool parse(const QString &line, bool *isCurrent);
@@ -43,13 +44,61 @@ private:
};
typedef QList<Branch> BranchList;
- const Type m_type;
+ /* Parse git output and populate m_branches. */
+ bool refreshBranches(const QString &workingDirectory, bool remoteBranches,
+ int *currentBranch, QString *errorMessage);
+ bool runGitBranchCommand(const QString &workingDirectory, const QStringList &additionalArgs, QString *output, QString *errorMessage);
+
+private:
+ QString toolTip(const QString &sha) const;
+
const Qt::ItemFlags m_flags;
- GitClient *m_client;
+ GitClient *m_client;
QString m_workingDirectory;
BranchList m_branches;
+};
+
+/* LocalBranchModel: Extends RemoteBranchModel by a read-only
+ * checkable column indicating the current branch. Provides an
+ * editable "Type here" new-branch-row at the bottom to create
+ * a new branch. */
+
+class LocalBranchModel : public RemoteBranchModel {
+ Q_OBJECT
+public:
+
+ explicit LocalBranchModel(GitClient *client,
+ QObject *parent = 0);
+
+ virtual bool refresh(const QString &workingDirectory, QString *errorMessage);
+
+ // is this the "type here" row?
+ bool isNewBranchRow(int row) const;
+ bool isNewBranchRow(const QModelIndex & index) const { return isNewBranchRow(index.row()); }
+
+ int currentBranch() const;
+
+ // QAbstractListModel
+ virtual int rowCount(const QModelIndex &parent = QModelIndex()) const;
+ virtual QVariant data(const QModelIndex &index, int role = Qt::DisplayRole) const;
+ virtual bool setData(const QModelIndex &index, const QVariant &value, int role = Qt::EditRole);
+ virtual Qt::ItemFlags flags(const QModelIndex &index) const;
+
+signals:
+ void newBranchCreated(const QString &);
+
+private slots:
+ void slotNewBranchDelayedRefresh();
+
+private:
+ bool checkNewBranchName(const QString &name) const;
+
+ const QVariant m_typeHere;
+ const QVariant m_typeHereToolTip;
+
int m_currentBranch;
+ QString m_newBranch;
};
}
diff --git a/src/plugins/help/helpplugin.cpp b/src/plugins/help/helpplugin.cpp
index bdc98b66ee..5ecb375240 100644
--- a/src/plugins/help/helpplugin.cpp
+++ b/src/plugins/help/helpplugin.cpp
@@ -83,7 +83,8 @@ void HelpManager::registerDocumentation(const QStringList &fileNames)
bool needsSetup = false;
{
QHelpEngineCore hc(m_helpEngine->collectionFile());
- hc.setupData();
+ if (!hc.setupData())
+ qWarning() << "Could not initialize help engine:" << hc.error();
foreach (const QString &fileName, fileNames) {
if (!QFile::exists(fileName))
continue;
@@ -132,7 +133,7 @@ bool HelpPlugin::initialize(const QStringList & /*arguments*/, QString *)
// FIXME shouldn't the help engine create the directory if it doesn't exist?
QFileInfo fi(m_core->settings()->fileName());
- QDir directory(fi.absolutePath());
+ QDir directory(fi.absolutePath()+"/qtcreator");
if (!directory.exists())
directory.mkpath(directory.absolutePath());
m_helpEngine = new QHelpEngine(directory.absolutePath()
diff --git a/src/plugins/qt4projectmanager/qt4project.cpp b/src/plugins/qt4projectmanager/qt4project.cpp
index 2a7fd0c242..dd61dbde09 100644
--- a/src/plugins/qt4projectmanager/qt4project.cpp
+++ b/src/plugins/qt4projectmanager/qt4project.cpp
@@ -566,7 +566,6 @@ QStringList Qt4Project::files(FilesMode fileMode) const
if (fileMode == AllFiles)
files += m_projectFiles->generatedFiles[i];
}
- files += m_projectFiles->proFiles;
return files;
}
diff --git a/src/plugins/quickopen/quickopentoolwindow.cpp b/src/plugins/quickopen/quickopentoolwindow.cpp
index 415e347a3a..b3232147f3 100644
--- a/src/plugins/quickopen/quickopentoolwindow.cpp
+++ b/src/plugins/quickopen/quickopentoolwindow.cpp
@@ -451,14 +451,25 @@ void QuickOpenToolWindow::show(const QString &text, int selectionStart, int sele
void QuickOpenToolWindow::filterSelected()
{
- const char * const TEXT = "<type here>";
+ QString searchText = "<type here>";
QAction *action = qobject_cast<QAction*>(sender());
QTC_ASSERT(action, return);
IQuickOpenFilter *filter = action->data().value<IQuickOpenFilter*>();
QTC_ASSERT(filter, return);
- show(filter->shortcutString() + " " + TEXT,
+ QString currentText = m_fileLineEdit->text().trimmed();
+ // add shortcut string at front or replace existing shortcut string
+ if (!currentText.isEmpty()) {
+ searchText = currentText;
+ foreach (IQuickOpenFilter *otherfilter, m_quickOpenPlugin->filter()) {
+ if (currentText.startsWith(otherfilter->shortcutString() + " ")) {
+ searchText = currentText.mid(otherfilter->shortcutString().length()+1);
+ break;
+ }
+ }
+ }
+ show(filter->shortcutString() + " " + searchText,
filter->shortcutString().length() + 1,
- QString(TEXT).length());
+ searchText.length());
updateCompletionList(m_fileLineEdit->text());
m_fileLineEdit->setFocus();
}
diff --git a/src/plugins/texteditor/completionwidget.cpp b/src/plugins/texteditor/completionwidget.cpp
index 2b2f8520e7..2c9f6017b7 100644
--- a/src/plugins/texteditor/completionwidget.cpp
+++ b/src/plugins/texteditor/completionwidget.cpp
@@ -260,9 +260,9 @@ void CompletionWidget::updatePositionAndSize(int startPos)
const QRect cursorRect = m_editor->cursorRect(startPos);
const QDesktopWidget *desktop = QApplication::desktop();
#ifdef Q_OS_MAC
- const QRect screen = desktop->availableGeometry(desktop->screenNumber(this));
+ const QRect screen = desktop->availableGeometry(desktop->screenNumber(m_editorWidget));
#else
- const QRect screen = desktop->screenGeometry(desktop->screenNumber(this));
+ const QRect screen = desktop->screenGeometry(desktop->screenNumber(m_editorWidget));
#endif
QPoint pos = cursorRect.bottomLeft();