WingHexExplorer2/3rdparty/qcodeedit2/lib/qcodeedit.cpp

410 lines
12 KiB
C++

/****************************************************************************
**
** Copyright (C) 2006-2009 fullmetalcoder <fullmetalcoder@hotmail.fr>
**
** This file is part of the Edyuk project <http://edyuk.org>
**
** This file may be used under the terms of the GNU General Public License
** version 3 as published by the Free Software Foundation and appearing in the
** file GPL.txt included in the packaging of this file.
**
** This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE
** WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
**
****************************************************************************/
#include "qcodeedit.h"
/*!
\file qcodeedit.cpp
\brief Implementation of the QCodeEdit class
*/
#include "qeditor.h"
#include "qpanel.h"
#include "qpanellayout.h"
#include <QAction>
#include <QDir>
#include <QEvent>
#include <QFileInfo>
#include <QMenu>
#include <QMetaObject>
#include <QStringList>
/*!
\class QCodeEdit
\brief A thin layer over QEditor
The QCodeEdit class provides simple means to associate panels with
editors and manage them.
*/
/*!
\internal
\class QPanelWatcher
A class designed to work around some limitations of the hide/show event
system and allow proper setting and conservation of default visibility for
panels.
*/
class QPanelWatcher : public QObject {
public:
QPanelWatcher(QCodeEdit *e) : qce(e) {}
bool eventFilter(QObject *o, QEvent *e) {
QPanel *p = qobject_cast<QPanel *>(o);
QAction *a = qce->toggleViewAction(p);
if (a) {
bool sig = a->signalsBlocked();
a->blockSignals(true);
if (a->isChecked() && e->type() == QEvent::Hide)
a->setChecked(false);
else if (!a->isChecked() && e->type() == QEvent::Show)
a->setChecked(true);
a->blockSignals(sig);
}
return QObject::eventFilter(o, e);
}
private:
QCodeEdit *qce;
};
QStringList __qce_data_path;
/*!
\brief Centralized access point to data fetching
*/
QString QCE::fetchDataFile(const QString &file) {
if (QFileInfo(file).isAbsolute())
return file;
foreach (QString dp, __qce_data_path) {
QDir d(dp);
if (d.exists(file))
return d.absoluteFilePath(file);
}
return file;
}
/*!
\return The list of pathes used by QCE to fetch data
*/
QStringList QCE::dataPathes() { return __qce_data_path; }
/*!
\brief Add a path to the list of pathes used to fetch data
*/
void QCE::addDataPath(const QString &path) {
if (!__qce_data_path.contains(path))
__qce_data_path << path;
}
QList<QCodeEdit *> QCodeEdit::m_instances;
/*!
\brief ctor
The created editor object comes with builtin actions.
*/
QCodeEdit::QCodeEdit(QWidget *p) : m_panelsMenu(0) {
m_editor = new QEditor(p);
m_watcher = new QPanelWatcher(this);
m_layout = new QPanelLayout(m_editor);
m_instances << this;
}
/*!
\brief ctor
\param actions whether the QEditor object should create builtin actions
*/
QCodeEdit::QCodeEdit(bool actions, QWidget *p) : m_panelsMenu(0) {
m_editor = new QEditor(actions, p);
m_watcher = new QPanelWatcher(this);
m_layout = new QPanelLayout(m_editor);
m_instances << this;
}
/*!
\brief ctor
\param layout structure of the panel layout
The created editor object comes with builtin actions.
*/
QCodeEdit::QCodeEdit(const QString &layout, QWidget *p) : m_panelsMenu(0) {
m_editor = new QEditor(p);
m_watcher = new QPanelWatcher(this);
m_layout = new QPanelLayout(layout, m_editor);
m_instances << this;
}
/*!
\brief ctor
\param layout structure of the panel layout
\param actions whether the QEditor object should create builtin actions
*/
QCodeEdit::QCodeEdit(const QString &layout, bool actions, QWidget *p)
: m_panelsMenu(0) {
m_editor = new QEditor(actions, p);
m_watcher = new QPanelWatcher(this);
m_layout = new QPanelLayout(layout, m_editor);
m_instances << this;
}
/*!
\brief ctor
\param e editor to manage
\param p panel layout to associate with the editor
*/
QCodeEdit::QCodeEdit(QEditor *e, QPanelLayout *p) : m_panelsMenu(0) {
m_editor = e;
m_watcher = new QPanelWatcher(this);
m_layout = p ? p : new QPanelLayout(m_editor);
m_instances << this;
}
/*!
\brief ctor
\param e editor to manage
\param l structure of the panel layout
*/
QCodeEdit::QCodeEdit(QEditor *e, const QString &l) : m_panelsMenu(0) {
m_editor = e;
m_watcher = new QPanelWatcher(this);
m_layout = new QPanelLayout(l, m_editor);
m_instances << this;
}
/*!
\brief dtor
\warning Destroyes the editor and the panel layout it manages
*/
QCodeEdit::~QCodeEdit() {
m_instances.removeAll(this);
delete m_watcher;
delete m_editor;
delete m_layout;
}
/*!
\return the managed editor
*/
QEditor *QCodeEdit::editor() const { return m_editor; }
/*!
\return the panel layout associated with the managed editor
*/
QPanelLayout *QCodeEdit::panelLayout() const { return m_layout; }
/*!
\brief Add a panel
\return Toggle view action for the added panel
\param panel panel to add
\param pos position of the panel in the layout
\param _add whether to add the show action of the panel to the menu of
the editor
*/
QAction *QCodeEdit::addPanel(QPanel *panel, Position pos, bool _add) {
panel->attach(m_editor);
QAction *a = new QAction(panel->name(), m_editor);
a->setCheckable(true);
a->setChecked(panel->defaultVisibility());
QObject::connect(a, SIGNAL(toggled(bool)), panel, SLOT(setVisible(bool)));
m_layout->addWidget(panel, QPanelLayout::Position(pos));
m_layout->update();
m_actions << a;
panel->installEventFilter(m_watcher);
if (_add) {
if (!m_panelsMenu) {
m_panelsMenu = new QMenu(QEditor::tr("Panels"), m_editor);
m_panelsMenu->menuAction()->setObjectName("panels");
m_editor->addAction(m_panelsMenu->menuAction(),
QEditor::tr("&View"), QString());
}
m_panelsMenu->addAction(a);
}
return a;
}
/*!
\overload
\return Toggle view action for the added panel
\param name name of panel to add
\param pos position of the panel in the layout
\param _add whether to add the show action of the panel to the menu of
the editor
*/
QAction *QCodeEdit::addPanel(const QString &name, Position pos, bool _add) {
return addPanel(QPanel::panel(name, m_editor), pos, _add);
}
/*!
\return whether the editor has a panel of the given \a type
*/
bool QCodeEdit::hasPanel(const QString &type) const {
if (!m_layout)
return false;
QList<QPanel *> l = m_layout->panels();
foreach (QPanel *p, l)
if (p->type() == type)
return true;
return false;
}
/*!
\return a list of panels added to the editor
\param type Type of panel to look for (no filtering is performed if
empty)
*/
QList<QPanel *> QCodeEdit::panels(const QString &type) const {
if (!m_layout)
return QList<QPanel *>();
QList<QPanel *> l = m_layout->panels();
if (type.isEmpty())
return l;
int i = 0;
while (i < l.count()) {
if (l.at(i)->type() == type) {
++i;
} else {
l.removeAt(i);
}
}
return l;
}
/*!
\return the toggle view action of a given panel
*/
QAction *QCodeEdit::toggleViewAction(QPanel *p) const {
int idx = panels().indexOf(p);
return idx == -1 ? 0 : m_actions.at(idx);
}
/*!
\brief Send a command to every panel of a given type
\param signature method name suitable for QMetaObject::invokeMethod()
\param args list of arguments suitable for QMetaObject::invokeMethod()
Example use :
\code
sendPanelCommand("Status", "setVisible" Q_COMMAND << Q_ARG(bool,
false)); \endcode
*/
void QCodeEdit::sendPanelCommand(const QString &type, const char *signature,
#if QT_VERSION >= QT_VERSION_CHECK(6, 0, 0)
const QList<QMetaMethodArgument> &args) {
#else
const QList<QGenericArgument> &args) {
#endif
QList<QPanel *> lp = panels();
// qDebug("looking for panel of type %s", qPrintable(type));
foreach (QPanel *p, lp) {
if (p && (p->type() == type)) {
// qDebug("found.");
// TODO : ask trolltech to provide an overloaded invokeMetaMethod()
// taking a QList<> instead of nine defaulted args...
if (args.isEmpty())
QMetaObject::invokeMethod(p, signature);
else if (args.count() == 1)
QMetaObject::invokeMethod(p, signature, args.at(0));
else if (args.count() == 2)
QMetaObject::invokeMethod(p, signature, args.at(0), args.at(1));
else if (args.count() == 3)
QMetaObject::invokeMethod(p, signature, args.at(0), args.at(1),
args.at(2));
else if (args.count() == 4)
QMetaObject::invokeMethod(p, signature, args.at(0), args.at(1),
args.at(2), args.at(3));
else if (args.count() == 5)
QMetaObject::invokeMethod(p, signature, args.at(0), args.at(1),
args.at(2), args.at(3), args.at(4));
else if (args.count() == 6)
QMetaObject::invokeMethod(p, signature, args.at(0), args.at(1),
args.at(2), args.at(3), args.at(4),
args.at(5));
else if (args.count() == 7)
QMetaObject::invokeMethod(p, signature, args.at(0), args.at(1),
args.at(2), args.at(3), args.at(4),
args.at(5), args.at(6));
else if (args.count() == 7)
QMetaObject::invokeMethod(p, signature, args.at(0), args.at(1),
args.at(2), args.at(3), args.at(4),
args.at(5), args.at(6));
else if (args.count() == 8)
QMetaObject::invokeMethod(p, signature, args.at(0), args.at(1),
args.at(2), args.at(3), args.at(4),
args.at(5), args.at(6), args.at(7));
else if (args.count() == 9)
QMetaObject::invokeMethod(p, signature, args.at(0), args.at(1),
args.at(2), args.at(3), args.at(4),
args.at(5), args.at(7), args.at(8));
else if (args.count() == 10)
QMetaObject::invokeMethod(p, signature, args.at(0), args.at(1),
args.at(2), args.at(3), args.at(4),
args.at(5), args.at(7), args.at(8),
args.at(9));
}
}
}
/*!
\return The QCodeEdit object managing a given editor or a null point if
the given editor is unmanaged
*/
QCodeEdit *QCodeEdit::manager(QEditor *e) {
foreach (QCodeEdit *m, m_instances)
if (m->m_editor == e)
return m;
return 0;
}
/*!
\brief The (first) managed editor editing a given file or a null pointer
if none found
*/
QEditor *QCodeEdit::managed(const QString &f) {
foreach (QCodeEdit *m, m_instances)
if (m && m->m_editor && (m->m_editor->fileName() == f))
return m->m_editor;
return 0;
}