OSDN Git Service

バイナリビューアを実装、他ビューアも自分描画に変更
authorMasayuki Satoh <miyabi.satoh@gmail.com>
Mon, 22 Sep 2014 02:13:29 +0000 (11:13 +0900)
committerMasayuki Satoh <miyabi.satoh@gmail.com>
Mon, 22 Sep 2014 02:13:29 +0000 (11:13 +0900)
31 files changed:
Gefu.pro
README.md
abstractview.h [deleted file]
foldermodel.cpp
folderpanel.cpp
folderview.cpp
folderview.h
global.cpp
global.h
hexview.cpp [new file with mode: 0644]
hexview.h [new file with mode: 0644]
imageview.cpp [new file with mode: 0644]
imageview.h [new file with mode: 0644]
mainwindow.cpp
mainwindow.h
mainwindow.ui
panel.cpp
panel.ui
preferencedialog.cpp
preferencedialog.h
preferencedialog.ui
preferences.cpp
preferences.h
simpleimageview.cpp [deleted file]
simpleimageview.h [deleted file]
simpletextview.cpp [deleted file]
simpletextview.h [deleted file]
textview.cpp [new file with mode: 0644]
textview.h [new file with mode: 0644]
thumbnailview.cpp
thumbnailview.h

index aa4a3b3..8ded24b 100644 (file)
--- a/Gefu.pro
+++ b/Gefu.pro
@@ -25,11 +25,9 @@ SOURCES += main.cpp\
     sortdialog.cpp \
     historydialog.cpp \
     preferencedialog.cpp \
-    simpletextview.cpp \
     folderview.cpp \
     folderpanel.cpp \
     bookmarkdialog.cpp \
-    simpleimageview.cpp \
     abstractworker.cpp \
     foldermodel.cpp \
     panel.cpp \
@@ -40,7 +38,10 @@ SOURCES += main.cpp\
     thumbnaildelegate.cpp \
     thumbnailworker.cpp \
     folderview_private.cpp \
-    filereadworker.cpp
+    filereadworker.cpp \
+    imageview.cpp \
+    hexview.cpp \
+    textview.cpp
 
 HEADERS  += mainwindow.h \
     renamesingledialog.h \
@@ -53,26 +54,26 @@ HEADERS  += mainwindow.h \
     sortdialog.h \
     historydialog.h \
     preferencedialog.h \
-    simpletextview.h \
     folderview.h \
     version.h \
     folderpanel.h \
     bookmarkdialog.h \
-    simpleimageview.h \
     abstractworker.h \
     foldermodel.h \
     panel.h \
     preferences.h \
     global.h \
     win32.h \
-    abstractview.h \
     abstractrenamedialog.h \
     thumbnailview.h \
     thumbnaildelegate.h \
     thumbnailworker.h \
     folderview_private.h \
     operationworker.h \
-    filereadworker.h
+    filereadworker.h \
+    imageview.h \
+    hexview.h \
+    textview.h
 
 FORMS    += mainwindow.ui \
     renamesingledialog.ui \
index 56b003c..b70b4c2 100644 (file)
--- a/README.md
+++ b/README.md
@@ -3,11 +3,11 @@ Gefu
 
 Gefu is an Experimental File Utility.
 
-  * 内蔵テキストビューアの自分描画
-  * バイナリエディタ
-
 #### 2014/09/18 Ver0.25
   * 内蔵ビューアでのファイル読み込みを別スレッド化しました。
+  * 内蔵バイナリビューアを実装しました。
+  * 内蔵イメージビューアを自前描画に変更しました。
+  * 内蔵テキストビューアを自前描画に変更しました。
 
 #### 2014/09/16 Ver0.24
   * ツールバーの表示/非表示を切り替えられるようにしました。
diff --git a/abstractview.h b/abstractview.h
deleted file mode 100644 (file)
index 56f13c7..0000000
+++ /dev/null
@@ -1,13 +0,0 @@
-#ifndef ABSTRACTVIEW_H
-#define ABSTRACTVIEW_H
-
-class AbstractView
-{
-public:
-    AbstractView() {}
-
-    virtual void    scaleUp() = 0;
-    virtual void    scaleDown() = 0;
-};
-
-#endif // ABSTRACTVIEW_H
index eb686d7..36d031a 100644 (file)
@@ -521,7 +521,7 @@ QVariant FolderModel::data(const QModelIndex &index, int role) const
             if (isDir(index)) {\r
                 return QString("<DIR>");\r
             }\r
-            return FileSizeToString(fileInfo(index).size());\r
+            return fileSizeToString(fileInfo(index).size());\r
 \r
         case LastModified: // 更新日時\r
             return fileInfo(index).lastModified().toString("yy/MM/dd hh:mm");\r
index 775079d..0b168c8 100644 (file)
@@ -288,7 +288,7 @@ void FolderPanel::model_dataChanged(const QModelIndex &topLeft, const QModelInde
             text += tr("%1個のファイル ").arg(numFiles);
         }
         if (!text.isEmpty()) {
-            text += tr("を選択 合計%1").arg(FileSizeToString(totalSize));
+            text += tr("を選択 合計%1").arg(fileSizeToString(totalSize));
         }
         ui->filterLabel->setText(text);
     }
index 3c95775..ee525d5 100644 (file)
@@ -14,7 +14,6 @@
 ///
 FolderView::FolderView(QWidget *parent) :
     QTableView(parent),
-    AbstractView(),
     m_p(this)
 {
 }
@@ -30,6 +29,7 @@ void FolderView::initialize(MainWindow *w)
     qDebug() << "FolderView::initialize()";
 
     connect(this, SIGNAL(doubleClicked(QModelIndex)), w, SLOT(onOpen(QModelIndex)));
+    connect(this, SIGNAL(prefs_updated()), w, SLOT(prefs_updated()));
     connect(&m_p, SIGNAL(copyItems(QStringList,QString)), w, SLOT(copyItems(QStringList,QString)));
     connect(&m_p, SIGNAL(moveItems(QStringList,QString)), w, SLOT(moveItems(QStringList,QString)));
 
@@ -38,6 +38,26 @@ void FolderView::initialize(MainWindow *w)
     viewport()->installEventFilter(w);
 }
 
+void FolderView::onScaleUp()
+{
+    Preferences prefs(this);
+    QFont font = prefs.getFolderViewFont();
+    font.setPointSize(font.pointSize() + 1);
+    prefs.setFolderViewFont(font);
+
+    emit prefs_updated();
+}
+
+void FolderView::onScaleDown()
+{
+    Preferences prefs(this);
+    QFont font = prefs.getFolderViewFont();
+    font.setPointSize(font.pointSize() - 1);
+    prefs.setFolderViewFont(font);
+
+    emit prefs_updated();
+}
+
 void FolderView::setModel(QAbstractItemModel *model)
 {
     if (this->model()) {
@@ -57,18 +77,3 @@ void FolderView::setModel(QAbstractItemModel *model)
     }
 }
 
-void FolderView::scaleUp()
-{
-    Preferences prefs(this);
-    QFont font = prefs.getFolderViewFont();
-    font.setPointSize(font.pointSize() + 1);
-    prefs.setFolderViewFont(font);
-}
-
-void FolderView::scaleDown()
-{
-    Preferences prefs(this);
-    QFont font = prefs.getFolderViewFont();
-    font.setPointSize(font.pointSize() - 1);
-    prefs.setFolderViewFont(font);
-}
index 5158caa..cb1366d 100644 (file)
@@ -1,14 +1,13 @@
 #ifndef FOLDERVIEW_H
 #define FOLDERVIEW_H
 
-#include "abstractview.h"
 #include "folderview_private.h"
 #include "foldermodel.h"
 
 #include <QTableView>
 class MainWindow;
 
-class FolderView : public QTableView, public AbstractView
+class FolderView : public QTableView
 {
     Q_OBJECT
 
@@ -22,17 +21,16 @@ private:
     FolderView_Private  m_p;
 
 signals:
+    void    prefs_updated();
 
 private slots:
+    void    onScaleUp();
+    void    onScaleDown();
 
     // QAbstractItemView interface
 public:
     void setModel(QAbstractItemModel *model);
 
-    // AbstractView interface
-public:
-    void scaleUp();
-    void scaleDown();
 };
 
 inline FolderModel *FolderView::folderModel() const
index 1a4a52d..938fb81 100644 (file)
@@ -7,7 +7,146 @@ void appendActionShortcut(QAction *action, const QString &ks)
     action->setShortcuts(shortcuts);
 }
 
-QString FileSizeToString(qint64 size)
+std::string detectCode(const QByteArray &bytes)
+{
+    const quint8 bEscape = 0x1B;
+    const quint8 bAt = 0x40;
+    const quint8 bDollar = 0x24;
+    const quint8 bAnd = 0x26;
+    const quint8 bOpen = 0x28;    //'('
+    const quint8 bB = 0x42;
+    const quint8 bD = 0x44;
+    const quint8 bJ = 0x4A;
+    const quint8 bI = 0x49;
+
+    int len = bytes.size();
+    quint8 b1, b2, b3, b4;
+
+//    bool isBinary = false;
+    for (int i = 0; i < len; i++) {
+        b1 = bytes[i];
+        if (b1 <= 0x06 || b1 == 0x7F || b1 == 0xFF) {
+            //'binary'
+            return "Binary";
+//            isBinary = true;
+//            if (b1 == 0x00 && i < len - 1 && static_cast<byte>(bytes[i + 1]) <= 0x7F) {
+//                return "UTF-16LE";
+//            }
+        }
+    }
+//    if (isBinary) {
+//        return "UTF-8";
+//    }
+
+    bool notJapanese = true;
+    for (int i = 0; i < len; i++) {
+        b1 = bytes[i];
+        if (b1 == bEscape || 0x80 <= b1) {
+            notJapanese = false;
+            break;
+        }
+    }
+    if (notJapanese) {
+        return "UTF-8";
+    }
+
+    for (int i = 0; i < len - 2; i++) {
+        b1 = bytes[i];
+        b2 = bytes[i + 1];
+        b3 = bytes[i + 2];
+
+        if (b1 == bEscape){
+            if ((b2 == bDollar && b3 == bAt) ||
+                (b2 == bDollar && b3 == bB) ||
+                (b2 == bOpen && (b3 == bB || b3 == bJ)) ||
+                (b2 == bOpen && b3 == bI))
+            {
+                return "ISO 2022-JP";
+            }
+            if (i < len - 3) {
+                b4 = bytes[i + 3];
+                if (b2 == bDollar && b3 == bOpen && b4 == bD) {
+                    return "ISO 2022-JP";
+                }
+                if (i < len - 5 &&
+                    b2 == bAnd && b3 == bAt && b4 == bEscape &&
+                    bytes[i + 4] == bDollar && bytes[i + 5] == bB)
+                {
+                    return "ISO 2022-JP";
+                }
+            }
+        }
+    }
+
+    int sjis = 0;
+    int euc = 0;
+    int utf8 = 0;
+    for (int i = 0; i < len - 1; i++) {
+        b1 = bytes[i];
+        b2 = bytes[i + 1];
+        if (((0x81 <= b1 && b1 <= 0x9F) || (0xE0 <= b1 && b1 <= 0xFC)) &&
+            ((0x40 <= b2 && b2 <= 0x7E) || (0x80 <= b2 && b2 <= 0xFC)))
+        {
+            sjis += 2;
+            i++;
+        }
+    }
+    for (int i = 0; i < len - 1; i++) {
+        b1 = bytes[i];
+        b2 = bytes[i + 1];
+        if (((0xA1 <= b1 && b1 <= 0xFE) && (0xA1 <= b2 && b2 <= 0xFE)) ||
+            (b1 == 0x8E && (0xA1 <= b2 && b2 <= 0xDF)))
+        {
+            euc += 2;
+            i++;
+        }
+        else if (i < len - 2) {
+            b3 = bytes[i + 2];
+            if (b1 == 0x8F && (0xA1 <= b2 && b2 <= 0xFE) &&
+                (0xA1 <= b3 && b3 <= 0xFE))
+            {
+                euc += 3;
+                i += 2;
+            }
+        }
+    }
+    for (int i = 0; i < len - 1; i++) {
+        b1 = bytes[i];
+        b2 = bytes[i + 1];
+        if ((0xC0 <= b1 && b1 <= 0xDF) && (0x80 <= b2 && b2 <= 0xBF)) {
+            utf8 += 2;
+            i++;
+        }
+        else if (i < len - 2) {
+            b3 = bytes[i + 2];
+            if ((0xE0 <= b1 && b1 <= 0xEF) && (0x80 <= b2 && b2 <= 0xBF) &&
+                (0x80 <= b3 && b3 <= 0xBF))
+            {
+                utf8 += 3;
+                i += 2;
+            }
+        }
+    }
+
+    if (euc > sjis && euc > utf8) {
+        return "EUC-JP";
+    }
+    else if (sjis > euc && sjis > utf8) {
+        return "Shift-JIS";
+    }
+    else if (utf8 > euc && utf8 > sjis) {
+        return "UTF-8";
+    }
+
+#ifdef Q_OS_WIN
+    return "Shift-JIS";
+#else
+    return "UTF-8";
+#endif
+
+}
+
+QString fileSizeToString(qint64 size)
 {
     if (size >= 1024 * 1024 * 1024) {
         return QString("%1GB").arg(int(10 * size / (1024 * 1024 * 1024)) / 10);
@@ -28,3 +167,5 @@ void reconnectAction(QAction *sender, const char *signal, QObject *reciever, con
     sender->disconnect();
     QObject::connect(sender, signal, reciever, slot);
 }
+
+
index 6cf176a..416cb41 100644 (file)
--- a/global.h
+++ b/global.h
@@ -11,7 +11,8 @@
 typedef QMap<QString, QString> StringMap;
 
 extern void appendActionShortcut(QAction *action, const QString &ks);
-extern QString FileSizeToString(qint64 size);
+extern std::string detectCode(const QByteArray &bytes);
+extern QString fileSizeToString(qint64 size);
 extern void reconnectAction(QAction *sender, const char *signal, QObject *reciever, const char *slot);
 
 #endif // GLOBAL_H
diff --git a/hexview.cpp b/hexview.cpp
new file mode 100644 (file)
index 0000000..57f7b6f
--- /dev/null
@@ -0,0 +1,285 @@
+#include "preferences.h"
+#include "hexview.h"
+
+#include <QApplication>
+#include <QClipboard>
+#include <QDebug>
+#include <QPainter>
+#include <QPaintEvent>
+#include <QScrollArea>
+
+const int HEXCHARS_IN_LINE = 3 * 16;
+const int BYTES_PER_LINE = 16;
+const int GAP_ADR_HEX = 1;
+const int GAP_HEX_ASCII = 3;
+
+HexView::HexView(QScrollArea *parent) :
+    QWidget(parent)
+{
+    m_scrollArea = parent;
+    this->setObjectName("hexView");
+    m_scrollArea->setWidget(this);
+
+    resetSelection(0);
+}
+
+void HexView::setData(const QByteArray &data)
+{
+    m_data = data;
+    adjust();
+}
+
+int HexView::addressChars() const
+{
+    return QString("%1").arg(m_data.size(), 0, 16).length();
+}
+
+void HexView::adjust()
+{
+    int lines = (m_data.size() / BYTES_PER_LINE) + 1;
+    setMinimumHeight((lines + 1) * m_charHeight);
+
+    int addressArea = (addressChars() + GAP_ADR_HEX) * m_charWidth;
+    int hexArea = HEXCHARS_IN_LINE * m_charWidth;
+    int asciiArea = (GAP_HEX_ASCII + BYTES_PER_LINE) * m_charWidth;
+    setMinimumWidth(addressArea + hexArea + asciiArea);
+}
+
+int HexView::cursorPos(const QPoint &pos)
+{
+    int result = -1;
+    if (xPosHex() <= pos.x() && pos.x() < xPosAscii()) {
+        int x = (pos.x() - xPosHex()) / m_charWidth;
+        if (x % 3 == 0) {
+            x /= 3;
+        }
+        else {
+            x = (x / 3) + 1;
+        }
+        int y = pos.y() / m_charHeight;
+
+        result = x + y * BYTES_PER_LINE;
+
+        qDebug() << x << y << result;
+    }
+
+    return result;
+}
+
+void HexView::resetSelection(int index)
+{
+    m_selectionBegin = index;
+    m_selectionEnd = index;
+    m_selectionInit = index;
+
+    emit copyAvailable(false);
+}
+
+void HexView::setSelection(int index)
+{
+    if (index > m_selectionInit) {
+        m_selectionBegin = m_selectionInit;
+        m_selectionEnd = index;
+    }
+    else {
+        m_selectionBegin = index;
+        m_selectionEnd = m_selectionInit;
+    }
+
+    emit copyAvailable(m_selectionBegin != m_selectionEnd);
+}
+
+int HexView::xPosHex() const
+{
+    return m_charWidth * (addressChars() + GAP_ADR_HEX);
+}
+
+int HexView::xPosAscii() const
+{
+    return xPosHex() + m_charWidth * (HEXCHARS_IN_LINE + GAP_HEX_ASCII);
+}
+
+void HexView::onCopy()
+{
+    QString selected;
+    for (int idx = m_selectionBegin; idx < m_selectionEnd; ++idx) {
+        quint8 c = static_cast<quint8>(m_data[idx]);
+        selected.append(QString("%1 ").arg(c, 2, 16, QChar('0')));
+    }
+
+    QClipboard *clipboard = qApp->clipboard();
+    clipboard->setText(selected.trimmed());
+}
+
+void HexView::onScaleDown()
+{
+    Preferences prefs(this);
+    QFont font = prefs.getHexViewFont();
+    font.setPointSize(font.pointSize() - 1);
+    prefs.setHexViewFont(font);
+
+    setVisible(true);
+    adjust();
+    update();
+}
+
+void HexView::onScaleUp()
+{
+    Preferences prefs(this);
+    QFont font = prefs.getHexViewFont();
+    font.setPointSize(font.pointSize() + 1);
+    prefs.setHexViewFont(font);
+
+    setVisible(true);
+    adjust();
+    update();
+}
+
+void HexView::onSelectAll()
+{
+    resetSelection(0);
+    setSelection(m_data.size());
+
+    update();
+}
+
+void HexView::setVisible(bool visible)
+{
+    if (visible) {
+        Preferences prefs(this);
+        QPalette pal = this->palette();
+        pal.setColor(this->backgroundRole(), prefs.getHexViewBgColor());
+        pal.setColor(this->foregroundRole(), prefs.getHexViewFgColor());
+        this->setPalette(pal);
+        this->setAutoFillBackground(true);
+        this->setFont(prefs.getHexViewFont());
+
+        m_charHeight = fontMetrics().height();
+        m_charWidth = fontMetrics().width('9');
+    }
+
+    QWidget::setVisible(visible);
+}
+
+void HexView::mousePressEvent(QMouseEvent *e)
+{
+    if (e->button() == Qt::LeftButton) {
+        int cPos = cursorPos(e->pos());
+        resetSelection(cPos);
+
+        update();
+    }
+}
+
+void HexView::mouseDoubleClickEvent(QMouseEvent *e)
+{
+    if (e->button() == Qt::LeftButton) {
+        int cPos = cursorPos(e->pos());
+        int lineHead = (cPos / BYTES_PER_LINE) * BYTES_PER_LINE;
+        resetSelection(lineHead);
+        setSelection(lineHead + BYTES_PER_LINE);
+
+        update();
+    }
+}
+
+void HexView::mouseMoveEvent(QMouseEvent *e)
+{
+    m_scrollArea->ensureVisible(e->x(), e->y());
+
+    int cPos = cursorPos(e->pos());
+    if (cPos != -1) {
+        setSelection(cPos);
+        update();
+    }
+}
+
+void HexView::keyPressEvent(QKeyEvent *)
+{
+}
+
+void HexView::paintEvent(QPaintEvent *e)
+{
+    QPainter painter(this);
+
+    // 描画対象となるデータの範囲
+    int firstLineIdx = ((e->rect().top() / m_charHeight) - m_charHeight) * BYTES_PER_LINE;
+    if (firstLineIdx < 0)
+        firstLineIdx = 0;
+    int lastLineIdx = ((e->rect().bottom() / m_charHeight) + m_charHeight) * BYTES_PER_LINE;
+    if (lastLineIdx > m_data.size())
+        lastLineIdx = m_data.size();
+    // 描画開始位置
+    int yPosStart = (firstLineIdx / BYTES_PER_LINE) * m_charHeight + m_charHeight;
+
+    // アドレスエリア
+    QRect addressRect(e->rect());
+    addressRect.setLeft(0);
+    addressRect.setWidth(m_charWidth * addressChars());
+    painter.fillRect(addressRect, Qt::gray);
+    painter.setPen(Qt::black);
+    for (int lineIdx = firstLineIdx, yPos = yPosStart;
+         lineIdx < lastLineIdx;
+         lineIdx += BYTES_PER_LINE, yPos += m_charHeight)
+    {
+        QString address = QString("%1")
+                .arg(lineIdx, addressChars(), 16, QChar('0'));
+        painter.drawText(addressRect.left(), yPos, address);
+    }
+
+    // バイナリエリア
+    for (int lineIdx = firstLineIdx, yPos = yPosStart;
+         lineIdx < lastLineIdx;
+         lineIdx += BYTES_PER_LINE, yPos += m_charHeight)
+    {
+        int xPos = xPosHex();
+        for (int colIdx = 0;
+             lineIdx + colIdx < m_data.size() && colIdx < BYTES_PER_LINE;
+             colIdx++, xPos += m_charWidth * 3)
+        {
+            int Idx = lineIdx + colIdx;
+            if (m_selectionBegin <= Idx && Idx < m_selectionEnd) {
+                painter.setBackground(this->palette().highlight());
+                painter.setBackgroundMode(Qt::OpaqueMode);
+                painter.setPen(this->palette().highlightedText().color());
+            }
+            else {
+                painter.setPen(this->palette().color(this->foregroundRole()));
+                painter.setBackgroundMode(Qt::TransparentMode);
+            }
+
+            quint8 ch = static_cast<quint8>(m_data[Idx]);
+            QString s = QString("%1").arg(ch, 2, 16, QChar('0'));
+            if (colIdx < 8) {
+                s.append(" ");
+                painter.drawText(xPos, yPos, s);
+            }
+            else {
+                s.prepend(" ");
+                painter.drawText(xPos, yPos, s);
+            }
+        }
+    }
+
+    // アスキーエリア
+    painter.setPen(this->palette().color(this->foregroundRole()));
+    painter.setBackgroundMode(Qt::TransparentMode);
+    for (int lineIdx = firstLineIdx, yPos = yPosStart;
+         lineIdx < lastLineIdx;
+         lineIdx += BYTES_PER_LINE, yPos += m_charHeight)
+    {
+        int xPos = xPosAscii();
+
+        for (int colIdx = 0;
+             lineIdx + colIdx < m_data.size() && colIdx < BYTES_PER_LINE;
+             colIdx++, xPos += m_charWidth)
+        {
+            quint8 ch = static_cast<quint8>(m_data[lineIdx + colIdx]);
+            if (!::isprint(ch) && ch != ' ') {
+                ch = '.';
+            }
+            QString s = QString(ch).toLatin1();
+            painter.drawText(xPos, yPos, s);
+        }
+    }
+}
diff --git a/hexview.h b/hexview.h
new file mode 100644 (file)
index 0000000..37c17a1
--- /dev/null
+++ b/hexview.h
@@ -0,0 +1,55 @@
+#ifndef HEXVIEW_H
+#define HEXVIEW_H
+
+#include <QWidget>
+class QScrollArea;
+
+class HexView : public QWidget
+{
+    Q_OBJECT
+public:
+    explicit HexView(QScrollArea *parent = 0);
+
+    void    setData(const QByteArray &data);
+
+private:
+    QScrollArea*    m_scrollArea;
+    QByteArray      m_data;
+    int             m_charHeight;
+    int             m_charWidth;
+    int             m_selectionBegin;
+    int             m_selectionEnd;
+    int             m_selectionInit;
+
+    int     addressChars() const;
+    void    adjust();
+    int     cursorPos(const QPoint &pos);
+    void    resetSelection(int index);
+    void    setSelection(int index);
+    int     xPosHex() const;
+    int     xPosAscii() const;
+
+
+signals:
+    void    copyAvailable(bool);
+    void    statusChanged(const QString &text);
+
+public slots:
+    void    onCopy();
+    void    onScaleDown();
+    void    onScaleUp();
+    void    onSelectAll();
+
+    // QWidget interface
+public slots:
+    void setVisible(bool visible);
+
+protected:
+    void mousePressEvent(QMouseEvent *e);
+    void mouseDoubleClickEvent(QMouseEvent *e);
+    void mouseMoveEvent(QMouseEvent *e);
+    void keyPressEvent(QKeyEvent *);
+    void paintEvent(QPaintEvent *e);
+};
+
+#endif // HEXVIEW_H
diff --git a/imageview.cpp b/imageview.cpp
new file mode 100644 (file)
index 0000000..569cdeb
--- /dev/null
@@ -0,0 +1,177 @@
+#include "preferences.h"
+#include "imageview.h"
+
+#include <QApplication>
+#include <QDebug>
+#include <QMouseEvent>
+#include <QPainter>
+#include <QScrollArea>
+#include <QScrollBar>
+
+ImageView::ImageView(QScrollArea *parent) :
+    QWidget(parent),
+    m_dragStartPos(-1, -1)
+{
+    m_scrollArea = parent;
+    m_scrollArea->setWidget(this);
+    setObjectName("imageView");
+    setCursor(Qt::OpenHandCursor);
+}
+
+void ImageView::setData(const QPixmap &pixmap)
+{
+    m_pixmap = pixmap;
+    m_rotateDeg = 0;
+    m_scaleFactor = -1;
+    resizePixmap();
+}
+
+double ImageView::scaleFactor()
+{
+    if (m_scaleFactor <= 0) {
+        // 等倍または縮小
+        double scaleX, scaleY;
+        if (m_rotateDeg == 90 || m_rotateDeg == 270) {
+            scaleX = 1.0 * m_scrollArea->size().height() / m_pixmap.width();
+            scaleY = 1.0 * m_scrollArea->size().width() / m_pixmap.height();
+        }
+        else {
+            scaleX = 1.0 * m_scrollArea->size().width() / m_pixmap.width();
+            scaleY = 1.0 * m_scrollArea->size().height() / m_pixmap.height();
+        }
+        if (m_scaleFactor == -1 && scaleX >= 1 && scaleY >= 1) {
+            return 1;
+        }
+        return qMin(scaleX, scaleY);
+    }
+
+    return m_scaleFactor;
+}
+
+void ImageView::resizePixmap()
+{
+    double scaleFactor = this->scaleFactor();
+    m_scaledPixmap = m_pixmap.scaled(m_pixmap.size() * scaleFactor,
+                                     Qt::IgnoreAspectRatio,
+                                     Qt::SmoothTransformation);
+    if (m_rotateDeg == 90 || m_rotateDeg == 270) {
+        setMinimumSize(m_scaledPixmap.height(), m_scaledPixmap.width());
+    }
+    else {
+        setMinimumSize(m_scaledPixmap.width(), m_scaledPixmap.height());
+    }
+
+    emit statusChanged(QString("%1 x %2 x %3(%4%)")
+                       .arg(m_pixmap.width())
+                       .arg(m_pixmap.height())
+                       .arg(m_pixmap.depth())
+                       .arg(static_cast<int>(scaleFactor * 100)));
+}
+
+void ImageView::onFitToWindow()
+{
+    qDebug() << "ImageView::onFitToWindow()";
+
+    m_scaleFactor = 0;
+    m_scaleFactor = this->scaleFactor();
+    resizePixmap();
+    update();
+    m_scaleFactor = 0;
+}
+
+void ImageView::onRotate90()
+{
+    m_rotateDeg += 90;
+    m_rotateDeg %= 360;
+    resizePixmap();
+    update();
+}
+
+void ImageView::onRotate180()
+{
+    m_rotateDeg += 180;
+    m_rotateDeg %= 360;
+    resizePixmap();
+    update();
+}
+
+void ImageView::onScaleDown()
+{
+    m_scaleFactor = this->scaleFactor() * 0.8;
+    resizePixmap();
+    update();
+}
+
+void ImageView::onScaleNormal()
+{
+    m_scaleFactor = 1;
+    resizePixmap();
+    update();
+}
+
+void ImageView::onScaleUp()
+{
+    m_scaleFactor = this->scaleFactor() * 1.25;
+    resizePixmap();
+    update();
+}
+
+void ImageView::setVisible(bool visible)
+{
+    if (visible) {
+        Preferences prefs(this);
+        QPalette pal = this->palette();
+        pal.setColor(this->backgroundRole(), prefs.getImageViewBgColor());
+        this->setPalette(pal);
+        this->setAutoFillBackground(true);
+    }
+
+    QWidget::setVisible(visible);
+}
+
+void ImageView::mousePressEvent(QMouseEvent *e)
+{
+    if (e->button() == Qt::LeftButton) {
+        setCursor(Qt::ClosedHandCursor);
+        m_dragStartPos = e->pos();
+    }
+}
+
+void ImageView::mouseReleaseEvent(QMouseEvent *)
+{
+    setCursor(Qt::OpenHandCursor);
+    m_dragStartPos = QPoint(-1, -1);
+}
+
+void ImageView::mouseMoveEvent(QMouseEvent *e)
+{
+    if (m_dragStartPos.x() == -1 && m_dragStartPos.y() == -1)
+        return;
+
+    if ((e->pos() - m_dragStartPos).manhattanLength() < qApp->startDragDistance())
+        return;
+
+    QScrollBar *hBar = m_scrollArea->horizontalScrollBar();
+    QScrollBar *vBar = m_scrollArea->verticalScrollBar();
+    QPoint delta = e->pos() - m_dragStartPos;
+    hBar->setValue(hBar->value() - delta.x());
+    vBar->setValue(vBar->value() - delta.y());
+}
+
+void ImageView::paintEvent(QPaintEvent *)
+{
+    QPainter painter(this);
+
+    painter.translate(size().width() / 2, size().height() / 2);
+    painter.rotate(m_rotateDeg);
+    painter.drawPixmap(-m_scaledPixmap.width() / 2,
+                       -m_scaledPixmap.height() / 2,
+                       m_scaledPixmap);
+}
+
+void ImageView::resizeEvent(QResizeEvent *e)
+{
+    QWidget::resizeEvent(e);
+
+    resizePixmap();
+}
diff --git a/imageview.h b/imageview.h
new file mode 100644 (file)
index 0000000..d585ee5
--- /dev/null
@@ -0,0 +1,50 @@
+#ifndef IMAGEVIEW_H
+#define IMAGEVIEW_H
+
+#include <QWidget>
+class QScrollArea;
+
+class ImageView : public QWidget
+{
+    Q_OBJECT
+public:
+    explicit ImageView(QScrollArea *parent = 0);
+
+    void    setData(const QPixmap &pixmap);
+
+private:
+    QScrollArea*    m_scrollArea;
+    QPixmap         m_pixmap;
+    QPixmap         m_scaledPixmap;
+    double          m_scaleFactor;
+    int             m_rotateDeg;
+    QPoint          m_dragStartPos;
+    QPoint          m_dragStartScrollPos;
+
+    double  scaleFactor();
+    void    resizePixmap();
+
+signals:
+    void    statusChanged(const QString &text);
+
+public slots:
+    void    onFitToWindow();
+    void    onRotate90();
+    void    onRotate180();
+    void    onScaleDown();
+    void    onScaleNormal();
+    void    onScaleUp();
+
+    // QWidget interface
+public slots:
+    void setVisible(bool visible);
+
+protected:
+    void mousePressEvent(QMouseEvent *e);
+    void mouseReleaseEvent(QMouseEvent *);
+    void mouseMoveEvent(QMouseEvent *e);
+    void paintEvent(QPaintEvent *);
+    void resizeEvent(QResizeEvent *e);
+};
+
+#endif // IMAGEVIEW_H
index ee3c458..99f79c7 100644 (file)
@@ -12,8 +12,6 @@
 #include "renameworker.h"\r
 #include "renamesingledialog.h"\r
 #include "renamemultidialog.h"\r
-#include "simpletextview.h"\r
-#include "simpleimageview.h"\r
 #include "sortdialog.h"\r
 #include "version.h"\r
 #include "mainwindow.h"\r
@@ -30,6 +28,7 @@
 #include <QMimeData>\r
 #include <QNetworkAccessManager>\r
 #include <QProcess>\r
+#include <QScrollArea>\r
 \r
 ///////////////////////////////////////////////////////////////////////////////\r
 /// \brief MainWindow::MainWindow\r
@@ -108,10 +107,7 @@ MainWindow::MainWindow(QWidget *parent) :
         onCheckUpdate(true);\r
     }\r
 \r
-    ui->LPanel->updateAppearance(prefs);\r
-    ui->LPanel->model()->updateAppearance(prefs);\r
-    ui->RPanel->updateAppearance(prefs);\r
-    ui->RPanel->model()->updateAppearance(prefs);\r
+    prefs_updated();\r
 \r
     connect(ui->FPanel, SIGNAL(showed(QWidget*)), this, SLOT(view_showed(QWidget*)));\r
 }\r
@@ -331,6 +327,7 @@ void MainWindow::view_currentChanged(const QModelIndex &current, const QModelInd
     statusBar()->showMessage(activeModel()->filePath(current));\r
 \r
     if (m_viewMode == ModePreview) {\r
+        view_statusChanged();\r
         inactivePanel()->setViewItem(current);\r
     }\r
 \r
@@ -642,6 +639,15 @@ bool MainWindow::onContextMenuEvent(QObject *obj, QContextMenuEvent *e)
         menu.addAction(ui->text_ConvertFromUTF16BE);\r
         menu.addAction(ui->text_ConvertFromUTF16LE);\r
         menu.addSeparator();\r
+        menu.addAction(ui->view_SelectAll);\r
+        menu.addAction(ui->text_Copy);\r
+        if (m_viewMode == ModeView) {\r
+            menu.addSeparator();\r
+            menu.addAction(ui->view_Back);\r
+        }\r
+    }\r
+    else if (obj->objectName() == "hexView") {\r
+        menu.addAction(ui->view_SelectAll);\r
         menu.addAction(ui->text_Copy);\r
         if (m_viewMode == ModeView) {\r
             menu.addSeparator();\r
@@ -683,12 +689,9 @@ bool MainWindow::onContextMenuEvent(QObject *obj, QContextMenuEvent *e)
         return false;\r
     }\r
 \r
-    QAction *selected = menu.exec(e->globalPos());\r
-    if (selected == ui->action_ScaleDown || selected == ui->action_ScaleUp) {\r
-        ui->image_FitToWindow->blockSignals(true);\r
-        ui->image_FitToWindow->setChecked(false);\r
-        ui->image_FitToWindow->blockSignals(false);\r
-    }\r
+    QString statusText = statusBar()->currentMessage();\r
+    menu.exec(e->globalPos());\r
+    statusBar()->showMessage(statusText);\r
 \r
     return true;\r
 }\r
@@ -916,6 +919,19 @@ void MainWindow::onOpen(const QModelIndex &index)
 }\r
 \r
 ///////////////////////////////////////////////////////////////////////////////\r
+/// \brief MainWindow::prefs_updated\r
+///\r
+/// 設定が変更された場合の処理を行います。\r
+///\r
+void MainWindow::prefs_updated()\r
+{\r
+    Preferences prefs(this);\r
+    ui->LPanel->updateAppearance(prefs);\r
+    ui->RPanel->updateAppearance(prefs);\r
+    ui->FPanel->updateAppearance(prefs);\r
+}\r
+\r
+///////////////////////////////////////////////////////////////////////////////\r
 /// \brief MainWindow::onOpenEditor\r
 /// \param path\r
 ///\r
@@ -1396,63 +1412,48 @@ void MainWindow::onKeyEndOther()
     sendEventOther(&event2);\r
 }\r
 \r
-///////////////////////////////////////////////////////////////////////////////\r
-/// \brief MainWindow::onScaleDown\r
-///\r
-/// 表示を縮小します。\r
-///\r
-void MainWindow::onScaleDown()\r
-{\r
-    qDebug() << "MainWindow::onScaleDown()";\r
-\r
-    AbstractView *view = dynamic_cast<AbstractView*>(qApp->focusWidget());\r
-    if (view) {\r
-        view->scaleDown();\r
-    }\r
-\r
-    Preferences prefs(this);\r
-    if (ui->LPanel->isVisible()) {\r
-        ui->LPanel->updateAppearance(prefs);\r
-        ui->LPanel->model()->updateAppearance(prefs);\r
-    }\r
-    if (ui->RPanel->isVisible()) {\r
-        ui->RPanel->updateAppearance(prefs);\r
-        ui->RPanel->model()->updateAppearance(prefs);\r
-    }\r
-    if (ui->FPanel->isVisible()) {\r
-        ui->FPanel->updateAppearance(prefs);\r
-        ui->FPanel->model()->updateAppearance(prefs);\r
-    }\r
-}\r
+/////////////////////////////////////////////////////////////////////////////////\r
+///// \brief MainWindow::onScaleDown\r
+/////\r
+///// 表示を縮小します。\r
+/////\r
+//void MainWindow::onScaleDown()\r
+//{\r
+//    qDebug() << "MainWindow::onScaleDown()";\r
 \r
-///////////////////////////////////////////////////////////////////////////////\r
-/// \brief MainWindow::onScaleUp\r
-///\r
-/// 表示を拡大します。\r
-///\r
-void MainWindow::onScaleUp()\r
-{\r
-    qDebug() << "MainWindow::onScaleUp()";\r
+//    AbstractView *view = dynamic_cast<AbstractView*>(qApp->focusWidget());\r
+//    if (view) {\r
+//        view->scaleDown();\r
+//    }\r
 \r
-    AbstractView *view = dynamic_cast<AbstractView*>(qApp->focusWidget());\r
-    if (view) {\r
-        view->scaleUp();\r
-    }\r
+//    Preferences prefs(this);\r
+//    ui->LPanel->updateAppearance(prefs);\r
+//    ui->RPanel->updateAppearance(prefs);\r
+//    ui->FPanel->updateAppearance(prefs);\r
+//}\r
+\r
+/////////////////////////////////////////////////////////////////////////////////\r
+///// \brief MainWindow::onScaleUp\r
+/////\r
+///// 表示を拡大します。\r
+/////\r
+//void MainWindow::onScaleUp()\r
+//{\r
+//    qDebug() << "MainWindow::onScaleUp()";\r
+\r
+//    AbstractView *view = dynamic_cast<AbstractView*>(qApp->focusWidget());\r
+//    if (view) {\r
+//        view->scaleUp();\r
+//    }\r
+//    else {\r
+//        qDebug() << qApp->focusWidget()->objectName();\r
+//    }\r
 \r
-    Preferences prefs(this);\r
-    if (ui->LPanel->isVisible()) {\r
-        ui->LPanel->updateAppearance(prefs);\r
-        ui->LPanel->model()->updateAppearance(prefs);\r
-    }\r
-    if (ui->RPanel->isVisible()) {\r
-        ui->RPanel->updateAppearance(prefs);\r
-        ui->RPanel->model()->updateAppearance(prefs);\r
-    }\r
-    if (ui->FPanel->isVisible()) {\r
-        ui->FPanel->updateAppearance(prefs);\r
-        ui->FPanel->model()->updateAppearance(prefs);\r
-    }\r
-}\r
+//    Preferences prefs(this);\r
+//    ui->LPanel->updateAppearance(prefs);\r
+//    ui->RPanel->updateAppearance(prefs);\r
+//    ui->FPanel->updateAppearance(prefs);\r
+//}\r
 \r
 ///////////////////////////////////////////////////////////////////////////////\r
 /// \brief MainWindow::initBookmarkMenu\r
@@ -1495,7 +1496,7 @@ void MainWindow::initBookmarkMenu()
 void MainWindow::sendEventOther(QEvent *event)\r
 {\r
     qDebug() << "MainWindow::sendEventOther()";\r
-\r
+#if 0\r
     // フォーカスを持たない、可視状態のビューを検索する\r
     foreach (QWidget *w, findChildren<QWidget*>()) {\r
         AbstractView *view = dynamic_cast<AbstractView*>(w);\r
@@ -1506,6 +1507,8 @@ void MainWindow::sendEventOther(QEvent *event)
             }\r
         }\r
     }\r
+#endif\r
+    qApp->sendEvent(inactivePanel()->visibleView(), event);\r
 }\r
 \r
 ///////////////////////////////////////////////////////////////////////////////\r
@@ -1578,19 +1581,7 @@ void MainWindow::showPreferenceDialog()
 \r
     PreferenceDialog dlg(this);\r
     if (dlg.exec() == QDialog::Accepted) {\r
-        Preferences prefs(this);\r
-        if (ui->LPanel->isVisible()) {\r
-            ui->LPanel->updateAppearance(prefs);\r
-            ui->LPanel->model()->updateAppearance(prefs);\r
-        }\r
-        if (ui->RPanel->isVisible()) {\r
-            ui->RPanel->updateAppearance(prefs);\r
-            ui->RPanel->model()->updateAppearance(prefs);\r
-        }\r
-        if (ui->FPanel->isVisible()) {\r
-            ui->FPanel->updateAppearance(prefs);\r
-            ui->FPanel->model()->updateAppearance(prefs);\r
-        }\r
+        prefs_updated();\r
     }\r
 }\r
 \r
@@ -1777,8 +1768,6 @@ void MainWindow::initActions()
     connect(ui->action_Rename, SIGNAL(triggered()), this, SLOT(onRename()));\r
     connect(ui->action_KeyRight, SIGNAL(triggered()), this, SLOT(onKeyRight()));\r
     connect(ui->action_RunCommand, SIGNAL(triggered()), this, SLOT(onRunCommand()));\r
-    connect(ui->action_ScaleDown, SIGNAL(triggered()), this, SLOT(onScaleDown()));\r
-    connect(ui->action_ScaleUp, SIGNAL(triggered()), this, SLOT(onScaleUp()));\r
     connect(ui->action_SearchNext, SIGNAL(triggered()), this, SLOT(onSearchNext()));\r
     connect(ui->action_SearchPrev, SIGNAL(triggered()), this, SLOT(onSearchPrev()));\r
     connect(ui->action_Setting, SIGNAL(triggered()), this, SLOT(showPreferenceDialog()));\r
@@ -1841,19 +1830,7 @@ void MainWindow::setActiveModel(FolderModel *m)
     connect(ui->action_MarkInvert, SIGNAL(triggered()), activeModel(), SLOT(onMarkInvert()));\r
     connect(ui->action_Refresh, SIGNAL(triggered()), activeModel(), SLOT(refresh()));\r
 \r
-    Preferences prefs(this);\r
-    if (ui->LPanel->isVisible()) {\r
-        ui->LPanel->updateAppearance(prefs);\r
-        ui->LPanel->model()->updateAppearance(prefs);\r
-    }\r
-    if (ui->RPanel->isVisible()) {\r
-        ui->RPanel->updateAppearance(prefs);\r
-        ui->RPanel->model()->updateAppearance(prefs);\r
-    }\r
-    if (ui->FPanel->isVisible()) {\r
-        ui->FPanel->updateAppearance(prefs);\r
-        ui->FPanel->model()->updateAppearance(prefs);\r
-    }\r
+    prefs_updated();\r
 }\r
 \r
 ///////////////////////////////////////////////////////////////////////////////\r
@@ -1986,7 +1963,7 @@ void MainWindow::setViewMode(Mode mode)
         break;\r
 \r
     case ModeView:\r
-        ui->FPanel->updateAppearance(Preferences(this));\r
+//        ui->FPanel->updateAppearance(Preferences(this));\r
         ui->FPanel->setViewItem(focusItemView()->currentIndex());\r
         ui->splitter->setVisible(false);\r
         ui->FPanel->setVisible(true);\r
@@ -2041,6 +2018,10 @@ void MainWindow::updateActions()
     bool toggleSearch = true;\r
 \r
     QWidget *w = qApp->focusWidget();\r
+    if (w->objectName() == "scrollArea") {\r
+        w = static_cast<QScrollArea*>(w)->widget();\r
+    }\r
+\r
     if (w->objectName() == "folderView" || w->objectName() == "thumbnailView") {\r
         setEnabledAllActions(true);\r
         // 履歴\r
@@ -2101,35 +2082,45 @@ void MainWindow::updateActions()
         isView = false;\r
     }\r
     else if (w->objectName() == "textView") {\r
-        SimpleTextView *v = static_cast<SimpleTextView*>(w);\r
         setEnabledAllActions(false);\r
         toggleSearch = false;\r
 \r
-        reconnectAction(ui->text_ConvertFromEUC, SIGNAL(triggered()), v, SLOT(convertFromEUC()));\r
-        reconnectAction(ui->text_ConvertFromJIS, SIGNAL(triggered()), v, SLOT(convertFromJIS()));\r
-        reconnectAction(ui->text_ConvertFromSJIS, SIGNAL(triggered()), v, SLOT(convertFromSJIS()));\r
-        reconnectAction(ui->text_ConvertFromUTF8, SIGNAL(triggered()), v, SLOT(convertFromUTF8()));\r
-        reconnectAction(ui->text_ConvertFromUTF16, SIGNAL(triggered()), v, SLOT(convertFromUTF16()));\r
-        reconnectAction(ui->text_ConvertFromUTF16BE, SIGNAL(triggered()), v, SLOT(convertFromUTF16BE()));\r
-        reconnectAction(ui->text_ConvertFromUTF16LE, SIGNAL(triggered()), v, SLOT(convertFromUTF16LE()));\r
-        reconnectAction(ui->text_Copy, SIGNAL(triggered()), v, SLOT(copy()));\r
+        reconnectAction(ui->text_ConvertFromEUC, SIGNAL(triggered()), w, SLOT(onConvertFromEUC()));\r
+        reconnectAction(ui->text_ConvertFromJIS, SIGNAL(triggered()), w, SLOT(onConvertFromJIS()));\r
+        reconnectAction(ui->text_ConvertFromSJIS, SIGNAL(triggered()), w, SLOT(onConvertFromSJIS()));\r
+        reconnectAction(ui->text_ConvertFromUTF8, SIGNAL(triggered()), w, SLOT(onConvertFromUTF8()));\r
+        reconnectAction(ui->text_ConvertFromUTF16, SIGNAL(triggered()), w, SLOT(onConvertFromUTF16()));\r
+        reconnectAction(ui->text_ConvertFromUTF16BE, SIGNAL(triggered()), w, SLOT(onConvertFromUTF16BE()));\r
+        reconnectAction(ui->text_ConvertFromUTF16LE, SIGNAL(triggered()), w, SLOT(onConvertFromUTF16LE()));\r
+        reconnectAction(ui->view_SelectAll, SIGNAL(triggered()), w, SLOT(onSelectAll()));\r
+        reconnectAction(ui->text_Copy, SIGNAL(triggered()), w, SLOT(onCopy()));\r
     }\r
     else if (w->objectName() == "imageView") {\r
-        SimpleImageView *v = static_cast<SimpleImageView*>(w);\r
         setEnabledAllActions(false);\r
         toggleSearch = false;\r
         isImageView = true;\r
 \r
-        reconnectAction(ui->image_FitToWindow, SIGNAL(toggled(bool)), v, SLOT(fitToWindow(bool)));\r
-        reconnectAction(ui->image_ScaleNormal, SIGNAL(toggled(bool)), v, SLOT(scaleNormal()));\r
-        reconnectAction(ui->image_Rotate90, SIGNAL(triggered()), v, SLOT(rotate90()));\r
-        reconnectAction(ui->image_Rotate180, SIGNAL(triggered()), v, SLOT(rotate180()));\r
+        reconnectAction(ui->image_FitToWindow, SIGNAL(triggered()), w, SLOT(onFitToWindow()));\r
+        reconnectAction(ui->image_ScaleNormal, SIGNAL(triggered()), w, SLOT(onScaleNormal()));\r
+        reconnectAction(ui->image_Rotate90, SIGNAL(triggered()), w, SLOT(onRotate90()));\r
+        reconnectAction(ui->image_Rotate180, SIGNAL(triggered()), w, SLOT(onRotate180()));\r
+    }\r
+    else if (w->objectName() == "hexView") {\r
+        setEnabledAllActions(false);\r
+        toggleSearch = false;\r
+\r
+        reconnectAction(ui->view_SelectAll, SIGNAL(triggered()), w, SLOT(onSelectAll()));\r
+        reconnectAction(ui->text_Copy, SIGNAL(triggered()), w, SLOT(onCopy()));\r
     }\r
     else if (w->objectName() == "progressBar") {\r
         setEnabledAllActions(false);\r
         toggleSearch = false;\r
         isView = false;\r
     }\r
+    else {\r
+        toggleSearch = false;\r
+        isView = false;\r
+    }\r
 \r
     ui->toggle_Toolbar->blockSignals(true);\r
     ui->toggle_Toolbar->setChecked(ui->mainToolBar->isVisible());\r
@@ -2158,6 +2149,10 @@ void MainWindow::updateActions()
         ui->action_ScaleDown->setText(tr("文字を小さく"));\r
         ui->action_ScaleUp->setText(tr("文字を大きく"));\r
     }\r
+    if (isView) {\r
+        reconnectAction(ui->action_ScaleDown, SIGNAL(triggered()), w, SLOT(onScaleDown()));\r
+        reconnectAction(ui->action_ScaleUp, SIGNAL(triggered()), w, SLOT(onScaleUp()));\r
+    }\r
 \r
     ui->toggle_FullMode->setEnabled(m_viewMode == ModeBasic || m_viewMode == ModeFull);\r
 \r
index 0b17b5d..223a8fd 100644 (file)
@@ -66,8 +66,6 @@ private slots:
     void    onOpenWith();\r
     void    onRename();\r
     void    onRunCommand();\r
-    void    onScaleDown();\r
-    void    onScaleUp();\r
     void    onSearchNext();\r
     void    onSearchPrev();\r
     void    onSplitCenter();\r
@@ -95,10 +93,11 @@ public slots:
     void    moveItems(const QStringList &list, const QString &tgtDir);\r
     void    onAddBookmark();\r
     void    onOpen(const QModelIndex &index = QModelIndex());\r
+    void    prefs_updated();\r
     void    view_copyAvailable(bool yes);\r
     void    view_currentChanged(const QModelIndex & current, const QModelIndex & previous);\r
     void    view_finished();\r
-    void    view_statusChanged(const QString &text);\r
+    void    view_statusChanged(const QString &text = QString());\r
     void    view_showed(QWidget* w);\r
 \r
 private:\r
index bee6703..b313c42 100644 (file)
    </property>\r
   </action>\r
   <action name="image_FitToWindow">\r
-   <property name="checkable">\r
-    <bool>true</bool>\r
-   </property>\r
    <property name="text">\r
     <string>ウィンドウにフィット</string>\r
    </property>\r
     <string>T</string>\r
    </property>\r
   </action>\r
+  <action name="view_SelectAll">\r
+   <property name="text">\r
+    <string>すべて選択</string>\r
+   </property>\r
+   <property name="shortcut">\r
+    <string>Ctrl+A</string>\r
+   </property>\r
+  </action>\r
  </widget>\r
  <layoutdefault spacing="6" margin="11"/>\r
  <customwidgets>\r
index e5732c3..a9186bf 100644 (file)
--- a/panel.cpp
+++ b/panel.cpp
@@ -1,12 +1,17 @@
 #include "filereadworker.h"
 #include "foldermodel.h"
 #include "folderview.h"
+#include "global.h"
+#include "hexview.h"
+#include "imageview.h"
 #include "mainwindow.h"
 #include "preferences.h"
+#include "textview.h"
 #include "panel.h"
 #include "ui_panel.h"
 
 #include <QDebug>
+#include <QTextCodec>
 
 ///////////////////////////////////////////////////////////////////////////////
 /// \brief Panel::Panel
@@ -20,9 +25,8 @@ Panel::Panel(QWidget *parent) :
     m_worker()
 {
     ui->setupUi(this);
-    ui->imageView->setVisible(false);
-    ui->textView->setVisible(false);
     ui->progressBar->setVisible(false);
+    ui->scrollArea->setVisible(false);
 }
 
 ///////////////////////////////////////////////////////////////////////////////
@@ -54,10 +58,9 @@ void Panel::initialize(MainWindow *w)
 {
     qDebug() << "Panel::initialize()";
 
-    ui->imageView->initialize(w);
     ui->folderPanel->initialize(w);
-    ui->textView->initialize(w);
     ui->progressBar->installEventFilter(w);
+    ui->scrollArea->installEventFilter(w);
 }
 
 ///////////////////////////////////////////////////////////////////////////////
@@ -97,9 +100,9 @@ void Panel::setViewItem(const QModelIndex &index)
     }
 
     ui->progressBar->setVisible(false);
+    ui->scrollArea->setVisible(false);
+    ui->folderPanel->setVisible(false);
     if (!index.isValid()) {
-        ui->imageView->setVisible(false);
-        ui->textView->setVisible(false);
         ui->folderPanel->setVisible(true);
         return;
     }
@@ -108,8 +111,6 @@ void Panel::setViewItem(const QModelIndex &index)
     QString path = m->filePath(index);
     if (m->isDir(index)) {
         model()->setRootPath(path);
-        ui->imageView->setVisible(false);
-        ui->textView->setVisible(false);
         ui->folderPanel->setVisible(true);
         return;
     }
@@ -120,9 +121,6 @@ void Panel::setViewItem(const QModelIndex &index)
     connect(m_worker, SIGNAL(resultReady(QByteArray)), this, SLOT(onReady(QByteArray)));
     ui->progressBar->setValue(0);
     ui->progressBar->setVisible(true);
-    ui->imageView->setVisible(false);
-    ui->textView->setVisible(false);
-    ui->folderPanel->setVisible(false);
 
     m_worker->open(path);
     m_worker->start();
@@ -144,17 +142,10 @@ void Panel::updateAppearance(const Preferences &prefs)
     this->setAutoFillBackground(true);
     this->setPalette(pal);
 
-    pal = ui->imageView->palette();
-    pal.setColor(QPalette::Base, prefs.getImageViewBgColor());
-    ui->imageView->setPalette(pal);
-
-    pal = ui->textView->palette();
-    pal.setColor(QPalette::Base, prefs.getTextViewBgColor());
-    pal.setColor(QPalette::Text, prefs.getTextViewFgColor());
-    ui->textView->setPalette(pal);
-    ui->textView->setFont(prefs.getTextViewFont());
-
     ui->folderPanel->updateAppearance(prefs);
+    if (model()) {
+        model()->updateAppearance(prefs);
+    }
 }
 
 ///////////////////////////////////////////////////////////////////////////////
@@ -163,11 +154,8 @@ void Panel::updateAppearance(const Preferences &prefs)
 ///
 QWidget *Panel::visibleView() const
 {
-    if (ui->textView->isVisible()) {
-        return ui->textView;
-    }
-    if (ui->imageView->isVisible()) {
-        return ui->imageView;
+    if (ui->scrollArea->isVisible()) {
+        return ui->scrollArea->widget();
     }
     if (ui->folderPanel->isVisible()) {
         return ui->folderPanel->itemView();
@@ -188,21 +176,47 @@ QWidget *Panel::visibleView() const
 ///
 void Panel::onReady(const QByteArray &data)
 {
+    MainWindow *mainWnd;
+    if (parent()->objectName() == "splitter") {
+        mainWnd = static_cast<MainWindow*>(parent()->parent()->parent());
+    }
+    else {
+        mainWnd = static_cast<MainWindow*>(parent()->parent());
+    }
     ui->progressBar->setVisible(false);
+    ui->folderPanel->setVisible(false);
+    ui->scrollArea->setVisible(true);
+    QWidget *w = ui->scrollArea->widget();
+    if (w) {
+        delete w;
+    }
 
     QPixmap pixmap;
     if (pixmap.loadFromData(data)) {
-        ui->imageView->setSource(pixmap);
-        ui->folderPanel->setVisible(false);
-        ui->textView->setVisible(false);
-        ui->imageView->setVisible(true);
-        emit showed(ui->imageView);
+        ImageView *view = new ImageView(ui->scrollArea);
+        connect(view, SIGNAL(statusChanged(QString)), mainWnd, SLOT(view_statusChanged(QString)));
+        view->installEventFilter(mainWnd);
+        view->setData(pixmap);
+        emit showed(view);
         return;
     }
 
-    ui->textView->setSource(data);
-    ui->folderPanel->setVisible(false);
-    ui->imageView->setVisible(false);
-    ui->textView->setVisible(true);
-    emit showed(ui->textView);
+    std::string code = detectCode(data.left(1024));
+    QTextCodec *codec = QTextCodec::codecForName(code.c_str());
+    if (codec) {
+        TextView *view = new TextView(ui->scrollArea);
+        connect(view, SIGNAL(copyAvailable(bool)), mainWnd, SLOT(view_copyAvailable(bool)));
+        connect(view, SIGNAL(statusChanged(QString)), mainWnd, SLOT(view_statusChanged(QString)));
+        view->installEventFilter(mainWnd);
+        view->setData(data);
+        emit showed(view);
+        return;
+    }
+
+    HexView *view = new HexView(ui->scrollArea);
+    connect(view, SIGNAL(copyAvailable(bool)), mainWnd, SLOT(view_copyAvailable(bool)));
+    connect(view, SIGNAL(statusChanged(QString)), mainWnd, SLOT(view_statusChanged(QString)));
+    view->installEventFilter(mainWnd);
+    view->setData(data);
+    emit showed(view);
 }
index d51761f..6fc339b 100644 (file)
--- a/panel.ui
+++ b/panel.ui
@@ -6,8 +6,8 @@
    <rect>
     <x>0</x>
     <y>0</y>
-    <width>400</width>
-    <height>300</height>
+    <width>261</width>
+    <height>239</height>
    </rect>
   </property>
   <property name="windowTitle">
@@ -30,9 +30,9 @@
     <number>0</number>
    </property>
    <item>
-    <widget class="SimpleTextView" name="textView">
-     <property name="plainText">
-      <string>TextView</string>
+    <widget class="QProgressBar" name="progressBar">
+     <property name="value">
+      <number>24</number>
      </property>
     </widget>
    </item>
     <widget class="FolderPanel" name="folderPanel" native="true"/>
    </item>
    <item>
-    <widget class="QProgressBar" name="progressBar">
-     <property name="value">
-      <number>24</number>
+    <widget class="QScrollArea" name="scrollArea">
+     <property name="frameShape">
+      <enum>QFrame::NoFrame</enum>
+     </property>
+     <property name="frameShadow">
+      <enum>QFrame::Plain</enum>
      </property>
+     <property name="widgetResizable">
+      <bool>true</bool>
+     </property>
+     <widget class="QWidget" name="scrollAreaWidgetContents">
+      <property name="geometry">
+       <rect>
+        <x>0</x>
+        <y>0</y>
+        <width>261</width>
+        <height>212</height>
+       </rect>
+      </property>
+     </widget>
     </widget>
    </item>
-   <item>
-    <widget class="SimpleImageView" name="imageView"/>
-   </item>
   </layout>
  </widget>
  <customwidgets>
    <header>folderpanel.h</header>
    <container>1</container>
   </customwidget>
-  <customwidget>
-   <class>SimpleTextView</class>
-   <extends>QPlainTextEdit</extends>
-   <header>simpletextview.h</header>
-  </customwidget>
-  <customwidget>
-   <class>SimpleImageView</class>
-   <extends>QGraphicsView</extends>
-   <header>simpleimageview.h</header>
-  </customwidget>
  </customwidgets>
  <resources/>
  <connections/>
index 89750cf..38ac0a2 100644 (file)
@@ -8,6 +8,7 @@
 #include <QDir>
 #include <QFileDialog>
 #include <QFontDialog>
+#include <QPainter>
 #include <QStandardPaths>
 
 PreferenceDialog::PreferenceDialog(QWidget *parent) :
@@ -17,6 +18,17 @@ PreferenceDialog::PreferenceDialog(QWidget *parent) :
     ui->setupUi(this);
     ui->tabWidget->setCurrentIndex(0);
     ui->lBoxSample->setText(QDir::homePath());
+    ui->fvHiddenSample->installEventFilter(this);
+    ui->fvMarkedSample->installEventFilter(this);
+    ui->fvNormalSample->installEventFilter(this);
+    ui->fvReadOnlySample->installEventFilter(this);
+    ui->fvSystemSample->installEventFilter(this);
+    ui->lBoxSample->installEventFilter(this);
+    ui->sBoxNormalSample->installEventFilter(this);
+    ui->sBoxUnmatchSample->installEventFilter(this);
+    ui->tvSample->installEventFilter(this);
+    ui->hvSample->installEventFilter(this);
+    ui->gvSample->installEventFilter(this);
 
     connect(ui->fvNormal, SIGNAL(clicked()), this, SLOT(chooseColor()));
     connect(ui->fvNormalBg, SIGNAL(clicked()), this, SLOT(chooseColor()));
@@ -32,7 +44,10 @@ PreferenceDialog::PreferenceDialog(QWidget *parent) :
     connect(ui->sBoxUnmatch, SIGNAL(clicked()), this, SLOT(chooseColor()));
     connect(ui->sBoxUnmatchBg, SIGNAL(clicked()), this, SLOT(chooseColor()));
     connect(ui->tvBg, SIGNAL(clicked()), this, SLOT(chooseColor()));
+    connect(ui->tvCtrl, SIGNAL(clicked()), this, SLOT(chooseColor()));
     connect(ui->tvFg, SIGNAL(clicked()), this, SLOT(chooseColor()));
+    connect(ui->hvBg, SIGNAL(clicked()), this, SLOT(chooseColor()));
+    connect(ui->hvFg, SIGNAL(clicked()), this, SLOT(chooseColor()));
     connect(ui->gvBg, SIGNAL(clicked()), this, SLOT(chooseColor()));
     connect(ui->allBg, SIGNAL(clicked()), this, SLOT(chooseColor()));
     connect(ui->allFg, SIGNAL(clicked()), this, SLOT(chooseColor()));
@@ -41,6 +56,7 @@ PreferenceDialog::PreferenceDialog(QWidget *parent) :
     connect(ui->lBoxFont, SIGNAL(clicked()), this, SLOT(chooseFont()));
     connect(ui->sBoxFont, SIGNAL(clicked()), this, SLOT(chooseFont()));
     connect(ui->tvFont, SIGNAL(clicked()), this, SLOT(chooseFont()));
+    connect(ui->hvFont, SIGNAL(clicked()), this, SLOT(chooseFont()));
     connect(ui->allFont, SIGNAL(clicked()), this, SLOT(chooseFont()));
 
     connect(ui->browseArchiver, SIGNAL(clicked()), this, SLOT(choosePath()));
@@ -81,6 +97,7 @@ PreferenceDialog::PreferenceDialog(QWidget *parent) :
     setFont(ui->lBoxFontSpec, prefs.getLocationBoxFont());
     setFont(ui->sBoxFontSpec, prefs.getSearchBoxFont());
     setFont(ui->tvFontSpec, prefs.getTextViewFont());
+    setFont(ui->hvFontSpec, prefs.getHexViewFont());
 
     ui->lineHeight->setValue(prefs.getLineHeight());
 
@@ -123,6 +140,10 @@ void PreferenceDialog::loadAppearance(Preferences &prefs)
 
     setPalette(ui->tvSample, QPalette::Base, prefs.getTextViewBgColor());
     setPalette(ui->tvSample, QPalette::Text, prefs.getTextViewFgColor());
+    setPalette(ui->tvSample, QPalette::BrightText, prefs.getTextViewCtrlColor());
+
+    setPalette(ui->hvSample, QPalette::Base, prefs.getHexViewBgColor());
+    setPalette(ui->hvSample, QPalette::Text, prefs.getHexViewFgColor());
 
     setPalette(ui->gvSample, QPalette::Base, prefs.getImageViewBgColor());
 
@@ -152,6 +173,10 @@ void PreferenceDialog::saveAppearance(Preferences &prefs)
 
     prefs.setTextViewBgColor(ui->tvSample->palette().base().color());
     prefs.setTextViewFgColor(ui->tvSample->palette().text().color());
+    prefs.setTextViewCtrlColor(ui->tvSample->palette().brightText().color());
+
+    prefs.setHexViewBgColor(ui->hvSample->palette().base().color());
+    prefs.setHexViewFgColor(ui->hvSample->palette().text().color());
 
     prefs.setImageViewBgColor(ui->gvSample->palette().base().color());
 
@@ -220,6 +245,15 @@ void PreferenceDialog::chooseColor()
     else if (sender() == ui->tvFg) {
         color = ui->tvSample->palette().text().color();
     }
+    else if (sender() == ui->tvCtrl) {
+        color = ui->tvSample->palette().brightText().color();
+    }
+    else if (sender() == ui->hvBg) {
+        color = ui->hvSample->palette().base().color();
+    }
+    else if (sender() == ui->hvFg) {
+        color = ui->hvSample->palette().text().color();
+    }
     else if (sender() == ui->gvBg) {
         color = ui->gvSample->palette().base().color();
     }
@@ -284,6 +318,15 @@ void PreferenceDialog::chooseColor()
     else if (sender() == ui->tvFg) {
         setPalette(ui->tvSample, QPalette::Text, color);
     }
+    else if (sender() == ui->tvCtrl) {
+        setPalette(ui->tvSample, QPalette::BrightText, color);
+    }
+    else if (sender() == ui->hvBg) {
+        setPalette(ui->hvSample, QPalette::Base, color);
+    }
+    else if (sender() == ui->hvFg) {
+        setPalette(ui->hvSample, QPalette::Text, color);
+    }
     else if (sender() == ui->gvBg) {
         setPalette(ui->gvSample, QPalette::Base, color);
     }
@@ -295,6 +338,7 @@ void PreferenceDialog::chooseColor()
         setPalette(ui->lBoxSample, QPalette::Base, color);
         setPalette(ui->sBoxNormalSample, QPalette::Base, color);
         setPalette(ui->tvSample, QPalette::Base, color);
+        setPalette(ui->hvSample, QPalette::Base, color);
         setPalette(ui->gvSample, QPalette::Base, color);
     }
     else if (sender() == ui->allFg) {
@@ -302,6 +346,7 @@ void PreferenceDialog::chooseColor()
         setPalette(ui->lBoxSample, QPalette::Text, color);
         setPalette(ui->sBoxNormalSample, QPalette::Text, color);
         setPalette(ui->tvSample, QPalette::Text, color);
+        setPalette(ui->hvSample, QPalette::Text, color);
     }
 }
 
@@ -320,6 +365,9 @@ void PreferenceDialog::chooseFont()
     else if (sender() == ui->tvFont) {
         font = ui->tvFontSpec->font();
     }
+    else if (sender() == ui->hvFont) {
+        font = ui->hvFontSpec->font();
+    }
     else if (sender() == ui->allFont) {
         font = ui->fvFontSpec->font();
     }
@@ -343,11 +391,15 @@ void PreferenceDialog::chooseFont()
     else if (sender() == ui->tvFont) {
         setFont(ui->tvFontSpec, font);
     }
+    else if (sender() == ui->hvFont) {
+        setFont(ui->hvFontSpec, font);
+    }
     else if (sender() == ui->allFont) {
         setFont(ui->fvFontSpec, font);
         setFont(ui->lBoxFontSpec, font);
         setFont(ui->sBoxFontSpec, font);
         setFont(ui->tvFontSpec, font);
+        setFont(ui->hvFontSpec, font);
     }
 }
 
@@ -449,6 +501,7 @@ void PreferenceDialog::accept()
     prefs.setLocationBoxFont(ui->lBoxFontSpec->font());
     prefs.setSearchBoxFont(ui->sBoxFontSpec->font());
     prefs.setTextViewFont(ui->tvFontSpec->font());
+    prefs.setHexViewFont(ui->hvFontSpec->font());
 
     prefs.setLineHeight(ui->lineHeight->value());
 
@@ -460,3 +513,27 @@ void PreferenceDialog::accept()
     QDialog::accept();
 }
 
+bool PreferenceDialog::eventFilter(QObject *obj, QEvent *event)
+{
+    if (event->type() == QEvent::Paint) {
+//        QPaintEvent *e = static_cast<QPaintEvent*>(event);
+        QLineEdit *edit = static_cast<QLineEdit*>(obj);
+
+        QPainter painter(edit);
+
+        painter.fillRect(edit->rect(), edit->palette().base());
+        painter.setPen(edit->palette().text().color());
+        painter.drawText(edit->rect(), Qt::AlignVCenter, edit->text());
+
+        if (edit->objectName() == "tvSample") {
+            QRect rcCtrl(edit->rect());
+            int textWidth = edit->fontMetrics().width(edit->text());
+            rcCtrl.setLeft(edit->rect().left() + textWidth);
+            painter.setPen(edit->palette().brightText().color());
+            painter.drawText(rcCtrl, Qt::AlignVCenter, QChar(0x21B5));
+        }
+        return true;
+    }
+
+    return false;
+}
index 0f7ab9c..3c56052 100644 (file)
@@ -35,6 +35,10 @@ private slots:
     // QDialog interface
 public slots:
     void accept();
+
+    // QObject interface
+public:
+    bool eventFilter(QObject *obj, QEvent *event);
 };
 
 #endif // PREFERENCEDIALOG_H
index 052cd28..82f7acd 100644 (file)
@@ -6,8 +6,8 @@
    <rect>
     <x>0</x>
     <y>0</y>
-    <width>673</width>
-    <height>553</height>
+    <width>713</width>
+    <height>569</height>
    </rect>
   </property>
   <property name="sizePolicy">
@@ -35,7 +35,7 @@
       <enum>QTabWidget::Rounded</enum>
      </property>
      <property name="currentIndex">
-      <number>0</number>
+      <number>1</number>
      </property>
      <widget class="QWidget" name="tabGeneral">
       <attribute name="title">
               <property name="verticalSpacing">
                <number>4</number>
               </property>
-              <item row="0" column="0">
-               <widget class="QLabel" name="label">
-                <property name="text">
-                 <string>通 常</string>
-                </property>
-               </widget>
-              </item>
               <item row="0" column="1">
                <widget class="QPushButton" name="sBoxNormal">
                 <property name="sizePolicy">
                 </property>
                </widget>
               </item>
+              <item row="1" column="0" colspan="3">
+               <widget class="QLineEdit" name="sBoxNormalSample">
+                <property name="focusPolicy">
+                 <enum>Qt::NoFocus</enum>
+                </property>
+                <property name="text">
+                 <string>abc123あいう</string>
+                </property>
+                <property name="readOnly">
+                 <bool>true</bool>
+                </property>
+               </widget>
+              </item>
               <item row="0" column="2">
                <widget class="QPushButton" name="sBoxNormalBg">
                 <property name="minimumSize">
                 </property>
                </widget>
               </item>
-              <item row="1" column="0" colspan="3">
-               <widget class="QLineEdit" name="sBoxNormalSample">
-                <property name="focusPolicy">
-                 <enum>Qt::NoFocus</enum>
-                </property>
+              <item row="0" column="0">
+               <widget class="QLabel" name="label">
                 <property name="text">
-                 <string>abc123あいう</string>
-                </property>
-                <property name="readOnly">
-                 <bool>true</bool>
+                 <string>通 常</string>
                 </property>
                </widget>
               </item>
               <property name="verticalSpacing">
                <number>4</number>
               </property>
-              <item row="0" column="0">
-               <widget class="QLabel" name="label_2">
-                <property name="text">
-                 <string>不一致</string>
-                </property>
-               </widget>
-              </item>
-              <item row="0" column="1">
-               <widget class="QPushButton" name="sBoxUnmatch">
-                <property name="sizePolicy">
-                 <sizepolicy hsizetype="Minimum" vsizetype="Fixed">
-                  <horstretch>0</horstretch>
-                  <verstretch>0</verstretch>
-                 </sizepolicy>
-                </property>
+              <item row="0" column="2">
+               <widget class="QPushButton" name="sBoxUnmatchBg">
                 <property name="minimumSize">
                  <size>
                   <width>0</width>
                  <enum>Qt::StrongFocus</enum>
                 </property>
                 <property name="text">
-                 <string>文字</string>
+                 <string>背景</string>
                 </property>
                </widget>
               </item>
-              <item row="0" column="2">
-               <widget class="QPushButton" name="sBoxUnmatchBg">
+              <item row="0" column="1">
+               <widget class="QPushButton" name="sBoxUnmatch">
+                <property name="sizePolicy">
+                 <sizepolicy hsizetype="Minimum" vsizetype="Fixed">
+                  <horstretch>0</horstretch>
+                  <verstretch>0</verstretch>
+                 </sizepolicy>
+                </property>
                 <property name="minimumSize">
                  <size>
                   <width>0</width>
                  <enum>Qt::StrongFocus</enum>
                 </property>
                 <property name="text">
-                 <string>背景</string>
+                 <string>文字</string>
                 </property>
                </widget>
               </item>
                 </property>
                </widget>
               </item>
+              <item row="0" column="0">
+               <widget class="QLabel" name="label_2">
+                <property name="text">
+                 <string>不一致</string>
+                </property>
+               </widget>
+              </item>
              </layout>
             </item>
            </layout>
                <enum>Qt::StrongFocus</enum>
               </property>
               <property name="text">
-               <string>文字</string>
+               <string>通常文字</string>
               </property>
              </widget>
             </item>
             <item row="0" column="1">
+             <widget class="QPushButton" name="tvCtrl">
+              <property name="sizePolicy">
+               <sizepolicy hsizetype="Minimum" vsizetype="Fixed">
+                <horstretch>0</horstretch>
+                <verstretch>0</verstretch>
+               </sizepolicy>
+              </property>
+              <property name="focusPolicy">
+               <enum>Qt::StrongFocus</enum>
+              </property>
+              <property name="text">
+               <string>制御文字</string>
+              </property>
+             </widget>
+            </item>
+            <item row="0" column="2">
              <widget class="QPushButton" name="tvBg">
               <property name="focusPolicy">
                <enum>Qt::StrongFocus</enum>
               </property>
              </widget>
             </item>
-            <item row="1" column="0" colspan="2">
+            <item row="1" column="0" colspan="3">
              <widget class="QLineEdit" name="tvSample">
               <property name="focusPolicy">
                <enum>Qt::NoFocus</enum>
           </widget>
          </item>
          <item>
+          <widget class="QGroupBox" name="groupBox_7">
+           <property name="title">
+            <string>内蔵バイナリビューア</string>
+           </property>
+           <layout class="QGridLayout" name="gridLayout_9">
+            <property name="verticalSpacing">
+             <number>4</number>
+            </property>
+            <item row="0" column="0">
+             <widget class="QPushButton" name="hvFg">
+              <property name="sizePolicy">
+               <sizepolicy hsizetype="Minimum" vsizetype="Fixed">
+                <horstretch>0</horstretch>
+                <verstretch>0</verstretch>
+               </sizepolicy>
+              </property>
+              <property name="focusPolicy">
+               <enum>Qt::StrongFocus</enum>
+              </property>
+              <property name="text">
+               <string>文字</string>
+              </property>
+             </widget>
+            </item>
+            <item row="0" column="1">
+             <widget class="QPushButton" name="hvBg">
+              <property name="focusPolicy">
+               <enum>Qt::StrongFocus</enum>
+              </property>
+              <property name="text">
+               <string>背景</string>
+              </property>
+             </widget>
+            </item>
+            <item row="1" column="0" colspan="2">
+             <widget class="QLineEdit" name="hvSample">
+              <property name="focusPolicy">
+               <enum>Qt::NoFocus</enum>
+              </property>
+              <property name="text">
+               <string>abc123あいう</string>
+              </property>
+              <property name="readOnly">
+               <bool>true</bool>
+              </property>
+             </widget>
+            </item>
+           </layout>
+          </widget>
+         </item>
+         <item>
           <widget class="QGroupBox" name="groupBox_4">
            <property name="title">
             <string>内蔵画像ビューア</string>
            </property>
           </spacer>
          </item>
-         <item>
-          <layout class="QVBoxLayout" name="verticalLayout_3">
-           <item>
-            <widget class="QPushButton" name="allFg">
-             <property name="focusPolicy">
-              <enum>Qt::StrongFocus</enum>
-             </property>
-             <property name="text">
-              <string>全ての通常文字を一括指定</string>
-             </property>
-            </widget>
-           </item>
-           <item>
-            <widget class="QPushButton" name="allBg">
-             <property name="focusPolicy">
-              <enum>Qt::StrongFocus</enum>
-             </property>
-             <property name="text">
-              <string>全ての通常背景を一括指定</string>
-             </property>
-            </widget>
-           </item>
-          </layout>
-         </item>
         </layout>
        </item>
        <item>
            </property>
           </spacer>
          </item>
+         <item>
+          <widget class="QPushButton" name="allFg">
+           <property name="focusPolicy">
+            <enum>Qt::StrongFocus</enum>
+           </property>
+           <property name="text">
+            <string>全ての通常文字を一括指定</string>
+           </property>
+          </widget>
+         </item>
+         <item>
+          <widget class="QPushButton" name="allBg">
+           <property name="focusPolicy">
+            <enum>Qt::StrongFocus</enum>
+           </property>
+           <property name="text">
+            <string>全ての通常背景を一括指定</string>
+           </property>
+          </widget>
+         </item>
         </layout>
        </item>
       </layout>
           </widget>
          </item>
          <item row="4" column="0">
+          <widget class="QPushButton" name="hvFont">
+           <property name="focusPolicy">
+            <enum>Qt::StrongFocus</enum>
+           </property>
+           <property name="text">
+            <string>内蔵バイナリビューアのフォント</string>
+           </property>
+          </widget>
+         </item>
+         <item row="4" column="1" colspan="2">
+          <widget class="QLabel" name="hvFontSpec">
+           <property name="text">
+            <string>font family, point</string>
+           </property>
+          </widget>
+         </item>
+         <item row="5" column="0">
           <widget class="QLabel" name="label_4">
            <property name="text">
             <string>フォルダビューの行の高さ(1〜2)</string>
            </property>
           </widget>
          </item>
-         <item row="4" column="1">
+         <item row="5" column="1">
           <widget class="QDoubleSpinBox" name="lineHeight">
            <property name="decimals">
             <number>2</number>
            </property>
           </widget>
          </item>
-         <item row="4" column="2">
+         <item row="5" column="2">
           <spacer name="horizontalSpacer_6">
            <property name="orientation">
             <enum>Qt::Horizontal</enum>
index 116b181..778699d 100644 (file)
@@ -307,7 +307,10 @@ IMPLEMENT_COLOR(SearchBoxBgColor, QPalette().base().color())
 IMPLEMENT_COLOR(SearchBoxUnmatchFgColor, QColor(255, 0, 0))
 IMPLEMENT_COLOR(SearchBoxUnmatchBgColor, QPalette().base().color())
 IMPLEMENT_COLOR(TextViewFgColor, QPalette().text().color())
+IMPLEMENT_COLOR(TextViewCtrlColor, Qt::cyan)
 IMPLEMENT_COLOR(TextViewBgColor, QPalette().base().color())
+IMPLEMENT_COLOR(HexViewFgColor, getTextViewFgColor())
+IMPLEMENT_COLOR(HexViewBgColor, getTextViewBgColor())
 IMPLEMENT_COLOR(ImageViewBgColor, QPalette().base().color())
 
 #define IMPLEMENT_DOUBLE(key, defVal)                           \
@@ -339,3 +342,4 @@ IMPLEMENT_FONT(FolderViewFont, DefaultFixedFont())
 IMPLEMENT_FONT(LocationBoxFont, DefaultFixedFont())
 IMPLEMENT_FONT(SearchBoxFont, DefaultFixedFont())
 IMPLEMENT_FONT(TextViewFont, DefaultFixedFont())
+IMPLEMENT_FONT(HexViewFont, getTextViewFont())
index d9cc9de..25ee4f2 100644 (file)
@@ -82,7 +82,10 @@ public:
     DECLARE_OBJECT(QColor, SearchBoxUnmatchFgColor);
     DECLARE_OBJECT(QColor, SearchBoxUnmatchBgColor);
     DECLARE_OBJECT(QColor, TextViewFgColor);
+    DECLARE_OBJECT(QColor, TextViewCtrlColor);
     DECLARE_OBJECT(QColor, TextViewBgColor);
+    DECLARE_OBJECT(QColor, HexViewFgColor);
+    DECLARE_OBJECT(QColor, HexViewBgColor);
     DECLARE_OBJECT(QColor, ImageViewBgColor);
 
     DECLARE_PRIMITIVE(double, DarkFacotr);
@@ -92,6 +95,7 @@ public:
     DECLARE_OBJECT(QFont, LocationBoxFont);
     DECLARE_OBJECT(QFont, SearchBoxFont);
     DECLARE_OBJECT(QFont, TextViewFont);
+    DECLARE_OBJECT(QFont, HexViewFont);
 
 signals:
 
diff --git a/simpleimageview.cpp b/simpleimageview.cpp
deleted file mode 100644 (file)
index 604d689..0000000
+++ /dev/null
@@ -1,209 +0,0 @@
-#include "mainwindow.h"
-#include "simpleimageview.h"
-
-#include <QDebug>
-#include <QSettings>
-#include <QKeyEvent>
-#include <QContextMenuEvent>
-#include <QResizeEvent>
-#include <QAction>
-#include <QMenu>
-
-///////////////////////////////////////////////////////////////////////////////
-/// \brief SimpleImageView::SimpleImageView
-/// \param parent   親ウィジェット
-///
-/// コンストラクタ
-///
-SimpleImageView::SimpleImageView(QWidget *parent) :
-    QGraphicsView(parent),
-    AbstractView(),
-    m_imgSrc(),
-    m_scene(this),
-    m_scaleFactor(0),
-    m_rotateDeg(0)
-{
-    setContextMenuPolicy(Qt::NoContextMenu);
-    setDragMode(ScrollHandDrag);
-    setScene(&m_scene);
-}
-
-///////////////////////////////////////////////////////////////////////////////
-/// \brief SimpleImageView::initialize
-/// \param w    メインウィンドウオブジェクト
-///
-/// 初期化処理を行います。
-///
-void SimpleImageView::initialize(MainWindow *w)
-{
-    connect(this, SIGNAL(statusChanged(QString)), w, SLOT(view_statusChanged(QString)));
-    installEventFilter(w);
-}
-
-///////////////////////////////////////////////////////////////////////////////
-/// \brief SimpleImageView::setSource
-/// \param pixmap
-///
-void SimpleImageView::setSource(const QPixmap &pixmap)
-{
-    qDebug() << "SimpleImageView::setSource()";
-
-    m_imgSrc = pixmap;
-    m_rotateDeg = 0;
-    m_scaleFactor = -1;
-
-    resizeImage();
-}
-
-///////////////////////////////////////////////////////////////////////////////
-/// \brief SimpleImageView::scaleFactor
-/// \return 倍率を返します。
-///
-double SimpleImageView::scaleFactor()
-{
-    // すでに倍率が指定されている場合は、そのまま。
-    if (m_scaleFactor > 0) {
-        return m_scaleFactor;
-    }
-
-    // ビューポートに対する適切な倍率を計算する
-    double scaleFactor, scaleX, scaleY;
-    if (m_rotateDeg == 90 || m_rotateDeg == 270) {
-        scaleX = 1.0 * viewport()->width() / m_imgSrc.height();
-        scaleY = 1.0 * viewport()->height() / m_imgSrc.width();
-    }
-    else {
-        scaleX = 1.0 * viewport()->width() / m_imgSrc.width();
-        scaleY = 1.0 * viewport()->height() / m_imgSrc.height();
-    }
-    scaleFactor =  (scaleX > scaleY) ? scaleY : scaleX;
-
-    // 縮小もしくは等倍の場合
-    if (m_scaleFactor == -1) {
-        return (scaleFactor > 1) ? 1 : scaleFactor;
-    }
-
-    return scaleFactor;
-}
-
-///////////////////////////////////////////////////////////////////////////////
-/// \brief SimpleImageView::sizeChanged
-///
-/// サイズ変更後の処理を行います。
-///
-void SimpleImageView::sizeChanged()
-{
-    QString str;
-    str = tr("%1 x %2 x %3(%4%)")
-            .arg(m_imgSrc.width())
-            .arg(m_imgSrc.height())
-            .arg(m_imgSrc.depth())
-            .arg(int(scaleFactor() * 100));
-    emit statusChanged(str);
-}
-
-///////////////////////////////////////////////////////////////////////////////
-/// \brief SimpleImageView::resizeImage
-/// \return 倍率
-///
-/// イメージの拡大・縮小と回転を行います。
-///
-double SimpleImageView::resizeImage()
-{
-    double scaleFactor = this->scaleFactor();
-    QPixmap scaledImg = m_imgSrc.scaled(scaleFactor * m_imgSrc.width(),
-                                        scaleFactor * m_imgSrc.height(),
-                                        Qt::IgnoreAspectRatio,
-                                        Qt::SmoothTransformation);
-    this->scene()->clear();
-    this->scene()->addPixmap(scaledImg);
-    this->setSceneRect(scaledImg.rect());
-    this->setTransform(QTransform());
-    this->translate(width() / 2, height() / 2);
-    this->rotate(m_rotateDeg);
-    sizeChanged();
-
-    return scaleFactor;
-}
-
-///////////////////////////////////////////////////////////////////////////////
-/// \brief SimpleImageView::fitToWindow
-/// \param checked  メニューのチェック状態
-///
-/// ウィンドウへのフィットを切り替えます。
-///
-void SimpleImageView::fitToWindow(bool checked)
-{
-    if (checked) {
-        m_scaleFactor = 0;
-    }
-
-    double scaleFactor = resizeImage();
-
-    if (!checked) {
-        m_scaleFactor = scaleFactor;
-    }
-}
-
-///////////////////////////////////////////////////////////////////////////////
-/// \brief SimpleImageView::scaleNormal
-///
-/// 等倍で表示します。
-///
-void SimpleImageView::scaleNormal()
-{
-    m_scaleFactor = 1;
-    resizeImage();
-}
-
-///////////////////////////////////////////////////////////////////////////////
-/// \brief SimpleImageView::rotate90
-///
-/// 右に90度回転します。
-///
-void SimpleImageView::rotate90()
-{
-    m_rotateDeg += 90;
-    m_rotateDeg %= 360;
-    resizeImage();
-}
-
-///////////////////////////////////////////////////////////////////////////////
-/// \brief SimpleImageView::rotate180
-///
-/// 180度回転します。
-///
-void SimpleImageView::rotate180()
-{
-    m_rotateDeg += 180;
-    m_rotateDeg %= 360;
-    resizeImage();
-}
-
-///////////////////////////////////////////////////////////////////////////////
-/// \brief SimpleImageView::resizeEvent
-/// \param event
-///
-void SimpleImageView::resizeEvent(QResizeEvent *event)
-{
-    resizeImage();
-    QGraphicsView::resizeEvent(event);
-}
-
-///////////////////////////////////////////////////////////////////////////////
-/// \brief SimpleImageView::scaleUp
-///
-void SimpleImageView::scaleUp()
-{
-    m_scaleFactor = scaleFactor() * 1.25;
-    resizeImage();
-}
-
-///////////////////////////////////////////////////////////////////////////////
-/// \brief SimpleImageView::scaleDown
-///
-void SimpleImageView::scaleDown()
-{
-    m_scaleFactor = scaleFactor() * 0.8;
-    resizeImage();
-}
diff --git a/simpleimageview.h b/simpleimageview.h
deleted file mode 100644 (file)
index d7ceef7..0000000
+++ /dev/null
@@ -1,49 +0,0 @@
-#ifndef SIMPLEIMAGEVIEW_H
-#define SIMPLEIMAGEVIEW_H
-
-#include "abstractview.h"
-
-#include <QGraphicsView>
-
-class MainWindow;
-
-class SimpleImageView : public QGraphicsView, public AbstractView
-{
-    Q_OBJECT
-public:
-    explicit SimpleImageView(QWidget *parent = 0);
-
-    void    initialize(MainWindow *w);
-    void    setSource(const QPixmap &pixmap);
-
-private:
-    QPixmap         m_imgSrc;
-    QGraphicsScene  m_scene;
-    double          m_scaleFactor;
-    int             m_rotateDeg;
-
-private:
-    double  scaleFactor();
-    void    sizeChanged();
-    double  resizeImage();
-
-signals:
-    void    statusChanged(const QString &info);
-
-public slots:
-    void    fitToWindow(bool checked);
-    void    scaleNormal();
-    void    rotate90();
-    void    rotate180();
-
-    // QWidget interface
-protected:
-    void resizeEvent(QResizeEvent *event);
-
-    // AbstractView interface
-public slots:
-    void    scaleUp();
-    void    scaleDown();
-};
-
-#endif // SIMPLEIMAGEVIEW_H
diff --git a/simpletextview.cpp b/simpletextview.cpp
deleted file mode 100644 (file)
index d78482b..0000000
+++ /dev/null
@@ -1,276 +0,0 @@
-#include "mainwindow.h"
-#include "preferences.h"
-#include "simpletextview.h"
-
-#include <QDebug>
-#include <QMenu>
-#include <QSettings>
-#include <QShortcut>
-#include <QTextCodec>
-#include <QStatusBar>
-#include <QApplication>
-
-///////////////////////////////////////////////////////////////////////////////
-/// \brief SimpleTextView::SimpleTextView
-/// \param parent   親ウィジェット
-///
-/// コンストラクタ
-///
-SimpleTextView::SimpleTextView(QWidget *parent) :
-    QPlainTextEdit(parent),
-    AbstractView(),
-    m_source()
-{
-    setReadOnly(true);
-    setContextMenuPolicy(Qt::NoContextMenu);
-}
-
-///////////////////////////////////////////////////////////////////////////////
-/// \brief SimpleTextView::initialize
-/// \param w    メインウィンドウオブジェクト
-///
-/// 初期化処理を行います。
-///
-void SimpleTextView::initialize(MainWindow *w)
-{
-    qDebug() << "SimpleTextView::initialize()";
-
-    connect(this, SIGNAL(statusChanged(QString)), w, SLOT(view_statusChanged(QString)));
-    connect(this, SIGNAL(copyAvailable(bool)), w, SLOT(view_copyAvailable(bool)));
-
-    installEventFilter(w);
-}
-
-///////////////////////////////////////////////////////////////////////////////
-/// \brief SimpleTextView::setSource
-/// \param source   表示するデータ
-///
-/// データを表示します。
-///
-void SimpleTextView::setSource(const QByteArray &source)
-{
-    qDebug() << "SimpleTextView::setSource()" << source.size();
-
-    m_source = source;
-    if (m_source.size() == 0) {
-        setPlainText("");
-        emit statusChanged("");
-        return;
-    }
-
-    std::string code = detectCode(m_source.left(1024));
-    QTextCodec *codec = QTextCodec::codecForName(code.c_str());
-
-    setPlainText(codec->toUnicode(m_source));
-
-    emit statusChanged(code.c_str());
-}
-
-void SimpleTextView::convertFromEUC()
-{
-    QTextCodec *codec = QTextCodec::codecForName("EUC-JP");
-    setPlainText(codec->toUnicode(m_source));
-    emit statusChanged("EUC-JP");
-}
-
-void SimpleTextView::convertFromJIS()
-{
-    QTextCodec *codec = QTextCodec::codecForName("ISO 2022-JP");
-    setPlainText(codec->toUnicode(m_source));
-    emit statusChanged("ISO 2022-JP");
-}
-
-void SimpleTextView::convertFromSJIS()
-{
-    QTextCodec *codec = QTextCodec::codecForName("Shift-JIS");
-    setPlainText(codec->toUnicode(m_source));
-    emit statusChanged("Shift-JIS");
-}
-
-void SimpleTextView::convertFromUTF8()
-{
-    QTextCodec *codec = QTextCodec::codecForName("UTF-8");
-    setPlainText(codec->toUnicode(m_source));
-    emit statusChanged("UTF-8");
-}
-
-void SimpleTextView::convertFromUTF16()
-{
-    QTextCodec *codec = QTextCodec::codecForName("UTF-16");
-    setPlainText(codec->toUnicode(m_source));
-    emit statusChanged("UTF-16");
-}
-
-void SimpleTextView::convertFromUTF16BE()
-{
-    QTextCodec *codec = QTextCodec::codecForName("UTF-16BE");
-    setPlainText(codec->toUnicode(m_source));
-    emit statusChanged("UTF-16BE");
-}
-
-void SimpleTextView::convertFromUTF16LE()
-{
-    QTextCodec *codec = QTextCodec::codecForName("UTF-16LE");
-    setPlainText(codec->toUnicode(m_source));
-    emit statusChanged("UTF-16LE");
-}
-
-// http://dobon.net/vb/dotnet/string/detectcode.html より拝借
-std::string SimpleTextView::detectCode(const QByteArray &bytes)
-{
-    typedef unsigned char byte;
-    const byte bEscape = 0x1B;
-    const byte bAt = 0x40;
-    const byte bDollar = 0x24;
-    const byte bAnd = 0x26;
-    const byte bOpen = 0x28;    //'('
-    const byte bB = 0x42;
-    const byte bD = 0x44;
-    const byte bJ = 0x4A;
-    const byte bI = 0x49;
-
-    int len = bytes.size();
-    byte b1, b2, b3, b4;
-
-    bool isBinary = false;
-    for (int i = 0; i < len; i++) {
-        b1 = bytes[i];
-        if (b1 <= 0x06 || b1 == 0x7F || b1 == 0xFF) {
-            //'binary'
-            isBinary = true;
-            if (b1 == 0x00 && i < len - 1 && static_cast<byte>(bytes[i + 1]) <= 0x7F) {
-                return "UTF-16LE";
-            }
-        }
-    }
-    if (isBinary) {
-        return "UTF-8";
-    }
-
-    bool notJapanese = true;
-    for (int i = 0; i < len; i++) {
-        b1 = bytes[i];
-        if (b1 == bEscape || 0x80 <= b1) {
-            notJapanese = false;
-            break;
-        }
-    }
-    if (notJapanese) {
-        return "UTF-8";
-    }
-
-    for (int i = 0; i < len - 2; i++) {
-        b1 = bytes[i];
-        b2 = bytes[i + 1];
-        b3 = bytes[i + 2];
-
-        if (b1 == bEscape){
-            if ((b2 == bDollar && b3 == bAt) ||
-                (b2 == bDollar && b3 == bB) ||
-                (b2 == bOpen && (b3 == bB || b3 == bJ)) ||
-                (b2 == bOpen && b3 == bI))
-            {
-                return "ISO 2022-JP";
-            }
-            if (i < len - 3) {
-                b4 = bytes[i + 3];
-                if (b2 == bDollar && b3 == bOpen && b4 == bD) {
-                    return "ISO 2022-JP";
-                }
-                if (i < len - 5 &&
-                    b2 == bAnd && b3 == bAt && b4 == bEscape &&
-                    bytes[i + 4] == bDollar && bytes[i + 5] == bB)
-                {
-                    return "ISO 2022-JP";
-                }
-            }
-        }
-    }
-
-    int sjis = 0;
-    int euc = 0;
-    int utf8 = 0;
-    for (int i = 0; i < len - 1; i++) {
-        b1 = bytes[i];
-        b2 = bytes[i + 1];
-        if (((0x81 <= b1 && b1 <= 0x9F) || (0xE0 <= b1 && b1 <= 0xFC)) &&
-            ((0x40 <= b2 && b2 <= 0x7E) || (0x80 <= b2 && b2 <= 0xFC)))
-        {
-            sjis += 2;
-            i++;
-        }
-    }
-    for (int i = 0; i < len - 1; i++) {
-        b1 = bytes[i];
-        b2 = bytes[i + 1];
-        if (((0xA1 <= b1 && b1 <= 0xFE) && (0xA1 <= b2 && b2 <= 0xFE)) ||
-            (b1 == 0x8E && (0xA1 <= b2 && b2 <= 0xDF)))
-        {
-            euc += 2;
-            i++;
-        }
-        else if (i < len - 2) {
-            b3 = bytes[i + 2];
-            if (b1 == 0x8F && (0xA1 <= b2 && b2 <= 0xFE) &&
-                (0xA1 <= b3 && b3 <= 0xFE))
-            {
-                euc += 3;
-                i += 2;
-            }
-        }
-    }
-    for (int i = 0; i < len - 1; i++) {
-        b1 = bytes[i];
-        b2 = bytes[i + 1];
-        if ((0xC0 <= b1 && b1 <= 0xDF) && (0x80 <= b2 && b2 <= 0xBF)) {
-            utf8 += 2;
-            i++;
-        }
-        else if (i < len - 2) {
-            b3 = bytes[i + 2];
-            if ((0xE0 <= b1 && b1 <= 0xEF) && (0x80 <= b2 && b2 <= 0xBF) &&
-                (0x80 <= b3 && b3 <= 0xBF))
-            {
-                utf8 += 3;
-                i += 2;
-            }
-        }
-    }
-
-    if (euc > sjis && euc > utf8) {
-        return "EUC-JP";
-    }
-    else if (sjis > euc && sjis > utf8) {
-        return "Shift-JIS";
-    }
-    else if (utf8 > euc && utf8 > sjis) {
-        return "UTF-8";
-    }
-
-#ifdef Q_OS_WIN
-    return "Shift-JIS";
-#else
-    return "UTF-8";
-#endif
-}
-
-
-void SimpleTextView::scaleUp()
-{
-    qDebug() << "SimpleTextView::scaleUp()";
-
-    Preferences prefs(this);
-    QFont font = prefs.getTextViewFont();
-    font.setPointSize(font.pointSize() + 1);
-    prefs.setTextViewFont(font);
-}
-
-void SimpleTextView::scaleDown()
-{
-    qDebug() << "SimpleTextView::scaleDown()";
-
-    Preferences prefs(this);
-    QFont font = prefs.getTextViewFont();
-    font.setPointSize(font.pointSize() - 1);
-    prefs.setTextViewFont(font);
-}
diff --git a/simpletextview.h b/simpletextview.h
deleted file mode 100644 (file)
index 02056f1..0000000
+++ /dev/null
@@ -1,42 +0,0 @@
-#ifndef SIMPLETEXTVIEW_H
-#define SIMPLETEXTVIEW_H
-
-#include "abstractview.h"
-
-#include <QPlainTextEdit>
-
-class MainWindow;
-
-class SimpleTextView : public QPlainTextEdit, public AbstractView
-{
-    Q_OBJECT
-public:
-    explicit SimpleTextView(QWidget *parent = 0);
-
-    void    initialize(MainWindow *w);
-    void    setSource(const QByteArray &source);
-
-private:
-    QByteArray m_source;
-
-    static std::string  detectCode(const QByteArray &bytes);
-
-signals:
-    void    statusChanged(const QString &info);
-
-public slots:
-    void    convertFromEUC();
-    void    convertFromJIS();
-    void    convertFromSJIS();
-    void    convertFromUTF8();
-    void    convertFromUTF16();
-    void    convertFromUTF16BE();
-    void    convertFromUTF16LE();
-
-    // AbstractView interface
-public:
-    void    scaleUp();
-    void    scaleDown();
-};
-
-#endif // SIMPLETEXTVIEW_H
diff --git a/textview.cpp b/textview.cpp
new file mode 100644 (file)
index 0000000..8e7d848
--- /dev/null
@@ -0,0 +1,413 @@
+#include "global.h"
+#include "preferences.h"
+#include "textview.h"
+
+#include <QApplication>
+#include <QClipboard>
+#include <QDebug>
+#include <QPainter>
+#include <QPaintEvent>
+#include <QScrollArea>
+#include <QTextCodec>
+
+const int GAP_LINE_TEXT = 1;
+const int MARGIN_RIGHT = 1;
+
+TextView::TextView(QScrollArea *parent) :
+    QWidget(parent)
+{
+    m_scrollArea = parent;
+    m_scrollArea->setWidget(this);
+    setObjectName("textView");
+
+    resetSelection(0);
+}
+
+void TextView::setData(const QByteArray &data)
+{
+    m_source = data;
+
+    std::string code = detectCode(data.left(1024));
+    convertFrom(code.c_str());
+}
+
+void TextView::adjust()
+{
+    // 行数をカウントする
+    int lineNum = 1;
+    int offset = 0;
+    for (; offset < m_data.size(); ++offset) {
+        if (m_data[offset] == '\r') {
+            if (offset + 1 < m_data.size() && m_data[offset + 1] == '\n') {
+                ++offset;
+            }
+            ++lineNum;
+        }
+        else if (m_data[offset] == '\n') {
+            ++lineNum;
+        }
+    }
+
+    // 行番号表示に必要な幅を取得する
+    int lineNumWidth = m_charWidth * lineNumChars(lineNum);
+    // テキストの表示開始位置
+    int xPosText = lineNumWidth + GAP_LINE_TEXT * m_charWidth;
+
+    setMinimumWidth(xPosText + m_charWidth * 4);
+
+    // 文字の表示位置を取得する
+    m_viewPositions.clear();
+    int x = 0;
+    int y = m_charHeight;
+    int lineWidth = 0;
+    int wrapLine = 0;
+    const int lineMaxWidth = width() - xPosText - MARGIN_RIGHT * m_charWidth;
+    for (lineNum = 1, offset = 0; offset < m_data.size(); ++offset) {
+        bool isEOL = false;
+        if (m_data[offset] == '\r') {
+            isEOL = true;
+            if (offset < m_data.size() - 1 && m_data[offset + 1] == '\n') {
+                ++offset;
+            }
+        }
+        if (m_data[offset] == '\n') {
+            isEOL = true;
+        }
+
+        ViewPosition vPos;
+        vPos.lineNum = lineNum;
+        vPos.offset = offset;
+
+        int charWidth = fontMetrics().width(m_data.mid(offset, 1));
+        int tabIndent = 0;
+        if (isEOL) {
+            charWidth = fontMetrics().width(0x21B5);
+        }
+        else if (m_data[offset] == '\t') {
+            tabIndent = ((lineWidth + m_tabWidth) / m_tabWidth) * m_tabWidth - lineWidth;
+            charWidth = fontMetrics().width("^");
+        }
+
+        if (x + charWidth >= lineMaxWidth) {
+            x = 0;
+            ++wrapLine;
+        }
+
+        vPos.x = xPosText + x;
+        vPos.y = y + wrapLine * m_charHeight;
+        m_viewPositions << vPos;
+
+        if (isEOL) {
+            lineWidth = 0;
+            x = 0;
+            y += (wrapLine + 1) * m_charHeight;
+            wrapLine = 0;
+            ++lineNum;
+        }
+        else {
+            if (m_data[offset] == '\t') {
+                x += tabIndent;
+                if (x > lineMaxWidth) {
+                    x = x - lineMaxWidth;
+                    ++wrapLine;
+                }
+            }
+            else {
+                x += charWidth;
+            }
+            lineWidth += charWidth + tabIndent;
+        }
+    }
+
+    if (!m_viewPositions.isEmpty()) {
+        setMinimumHeight(m_viewPositions.last().y + m_charHeight);
+    }
+}
+
+void TextView::convertFrom(const char *code)
+{
+    QTextCodec *codec = QTextCodec::codecForName(code);
+    m_data = codec->toUnicode(m_source);
+    adjust();
+    resetSelection(0);
+    update();
+
+    emit statusChanged(code);
+}
+
+int TextView::cursorPos(const QPoint &pos)
+{
+    int n;
+    int y;
+    for (n = 0; n < m_viewPositions.size(); n++) {
+        if (pos.y() < m_viewPositions[n].y) {
+            y = m_viewPositions[n].y;
+            break;
+        }
+    }
+
+    for(; n < m_viewPositions.size(); n++) {
+        if (pos.x() < m_viewPositions[n].x) {
+            return n - 1;
+        }
+        if (y < m_viewPositions[n].y) {
+            return n;
+        }
+    }
+
+    return n;
+}
+
+int TextView::lineNumChars(int lines) const
+{
+    if (lines == -1) {
+        if (m_viewPositions.isEmpty()) {
+            return 0;
+        }
+        lines = m_viewPositions.last().lineNum;
+    }
+    return QString("%1").arg(lines).size() + 1;
+}
+
+void TextView::resetSelection(int index)
+{
+    m_selectionInit = index;
+    m_selectionBegin = index;
+    m_selectionEnd = index;
+
+    emit copyAvailable(false);
+}
+
+void TextView::setSelection(int index)
+{
+    if (index > m_selectionInit) {
+        m_selectionBegin = m_selectionInit;
+        m_selectionEnd = index;
+    }
+    else {
+        m_selectionBegin = index;
+        m_selectionEnd = m_selectionInit;
+    }
+
+    emit copyAvailable(m_selectionBegin != m_selectionEnd);
+}
+
+void TextView::onConvertFromEUC()
+{
+    convertFrom("EUC-JP");
+}
+
+void TextView::onConvertFromJIS()
+{
+    convertFrom("ISO 2022-JP");
+}
+
+void TextView::onConvertFromSJIS()
+{
+    convertFrom("Shift-JIS");
+}
+
+void TextView::onConvertFromUTF8()
+{
+    convertFrom("UTF-8");
+}
+
+void TextView::onConvertFromUTF16()
+{
+    convertFrom("UTF-16");
+}
+
+void TextView::onConvertFromUTF16BE()
+{
+    convertFrom("UTF-16BE");
+}
+
+void TextView::onConvertFromUTF16LE()
+{
+    convertFrom("UTF-16LE");
+}
+
+void TextView::onCopy()
+{
+    QString selected;
+    int length = m_viewPositions[m_selectionEnd].offset -
+            m_viewPositions[m_selectionBegin].offset;
+
+    selected = m_data.mid(m_viewPositions[m_selectionBegin].offset, length);
+
+    QClipboard *clipboard = qApp->clipboard();
+    clipboard->setText(selected);
+}
+
+void TextView::onScaleDown()
+{
+    Preferences prefs(this);
+    QFont font = prefs.getTextViewFont();
+    font.setPointSize(font.pointSize() - 1);
+    prefs.setTextViewFont(font);
+
+    setVisible(true);
+    adjust();
+    update();
+}
+
+void TextView::onScaleUp()
+{
+    Preferences prefs(this);
+    QFont font = prefs.getTextViewFont();
+    font.setPointSize(font.pointSize() + 1);
+    prefs.setTextViewFont(font);
+
+    setVisible(true);
+    adjust();
+    update();
+}
+
+void TextView::onSelectAll()
+{
+    m_selectionInit = 0;
+    m_selectionBegin = 0;
+    m_selectionEnd = m_viewPositions.size();
+}
+
+void TextView::setVisible(bool visible)
+{
+    if (visible) {
+        Preferences prefs(this);
+        QPalette pal = this->palette();
+        pal.setColor(this->backgroundRole(), prefs.getTextViewBgColor());
+        pal.setColor(this->foregroundRole(), prefs.getTextViewFgColor());
+        pal.setBrush(QPalette::BrightText, prefs.getTextViewCtrlColor());
+        this->setPalette(pal);
+        this->setAutoFillBackground(true);
+        this->setFont(prefs.getTextViewFont());
+
+        m_charHeight = fontMetrics().height();
+        m_charWidth = fontMetrics().width('9');
+        m_tabWidth = 8 * m_charWidth;
+    }
+
+    QWidget::setVisible(visible);
+}
+
+void TextView::mousePressEvent(QMouseEvent *e)
+{
+    if (e->button() == Qt::LeftButton) {
+        int cPos = cursorPos(e->pos());
+        resetSelection(cPos);
+
+        update();
+    }
+}
+
+void TextView::mouseDoubleClickEvent(QMouseEvent *e)
+{
+    if (e->button() == Qt::LeftButton) {
+        int cPos = cursorPos(e->pos());
+        if (cPos >= m_viewPositions.size()) {
+            cPos = m_viewPositions.size() - 1;
+        }
+        int y = m_viewPositions[cPos].y;
+
+        int n;
+        for (n = cPos; n >= 0; n--) {
+            if (m_viewPositions[n].y != y) {
+                ++n;
+                break;
+            }
+        }
+        resetSelection(n);
+
+        for (n = cPos; n < m_viewPositions.size(); n++) {
+            if (m_viewPositions[n].y != y) {
+                break;
+            }
+        }
+        setSelection(n - 1);
+
+        update();
+    }
+}
+
+void TextView::mouseMoveEvent(QMouseEvent *e)
+{
+    m_scrollArea->ensureVisible(e->x(), e->y());
+
+    int cPos = cursorPos(e->pos());
+    setSelection(cPos);
+    update();
+}
+
+void TextView::paintEvent(QPaintEvent *e)
+{
+    QPainter painter(this);
+
+    // 行番号エリア
+    QRect lineNumRect(e->rect());
+    lineNumRect.setLeft(0);
+    lineNumRect.setWidth(m_charWidth * lineNumChars());
+    painter.fillRect(lineNumRect, Qt::gray);
+
+    int prevLine = -1;
+    int idx;
+    for (idx = 0;
+         idx < m_viewPositions.size() &&
+            m_viewPositions[idx].y < e->rect().top();
+         ++idx)
+    {
+        prevLine = m_viewPositions[idx].lineNum;
+    }
+
+    painter.setPen(this->palette().color(this->foregroundRole()));
+    for (;
+         idx < m_viewPositions.size() &&
+            m_viewPositions[idx].y <= e->rect().bottom() + m_charHeight;
+         ++idx)
+    {
+        const ViewPosition &vPos = m_viewPositions[idx];
+
+        // 行番号
+        if (vPos.lineNum != prevLine) {
+            prevLine = vPos.lineNum;
+            painter.setPen(Qt::black);
+            painter.setBackgroundMode(Qt::TransparentMode);
+            QString lineNumber = QString("%1").arg(vPos.lineNum);
+            painter.drawText(
+                        lineNumRect.right() - fontMetrics().width(lineNumber),
+                        vPos.y,
+                        lineNumber);
+        }
+
+        if (m_selectionBegin <= idx && idx < m_selectionEnd) {
+            painter.setBackground(this->palette().highlight());
+            painter.setBackgroundMode(Qt::OpaqueMode);
+            painter.setPen(this->palette().highlightedText().color());
+        }
+        else {
+            painter.setPen(this->palette().color(this->foregroundRole()));
+            painter.setBackgroundMode(Qt::TransparentMode);
+        }
+
+        QString ch = m_data.mid(vPos.offset, 1);
+        if (ch == "\r" || ch == "\n") {
+            painter.setPen(this->palette().color(QPalette::BrightText));
+            painter.drawText(vPos.x, vPos.y, QChar(0x21B5));
+            painter.setPen(this->palette().color(this->foregroundRole()));
+        }
+        else if (ch == "\t") {
+            painter.setPen(this->palette().color(QPalette::BrightText));
+            painter.drawText(vPos.x, vPos.y, "^");
+            painter.setPen(this->palette().color(this->foregroundRole()));
+        }
+        else {
+            painter.drawText(vPos.x, vPos.y, ch);
+        }
+    }
+}
+
+void TextView::resizeEvent(QResizeEvent *e)
+{
+    QWidget::resizeEvent(e);
+
+    adjust();
+}
diff --git a/textview.h b/textview.h
new file mode 100644 (file)
index 0000000..a53dc0f
--- /dev/null
@@ -0,0 +1,75 @@
+#ifndef TEXTVIEW_H
+#define TEXTVIEW_H
+
+#include <QWidget>
+class QScrollArea;
+
+class TextView : public QWidget
+{
+    Q_OBJECT
+public:
+    explicit TextView(QScrollArea *parent = 0);
+
+    void    setData(const QByteArray &data);
+
+private:
+    struct ViewPosition {
+        int lineNum;    // 行番号
+        int offset;     // 文字列先頭からのオフセット
+        int x;          // X座標
+        int y;          // Y座標
+
+        ViewPosition() :
+            lineNum(0), offset(0), x(0), y(0)
+        {
+        }
+    };
+
+    QScrollArea*            m_scrollArea;
+    QByteArray              m_source;
+    QString                 m_data;
+    int                     m_charHeight;
+    int                     m_charWidth;
+    int                     m_tabWidth;
+    QVector<ViewPosition>   m_viewPositions;
+    int                     m_selectionBegin;
+    int                     m_selectionEnd;
+    int                     m_selectionInit;
+
+    void    adjust();
+    void    convertFrom(const char *code);
+    int     cursorPos(const QPoint &pos);
+    int     lineNumChars(int lines = -1) const;
+    void    resetSelection(int index);
+    void    setSelection(int index);
+
+signals:
+    void    copyAvailable(bool);
+    void    statusChanged(const QString &text);
+
+public slots:
+    void    onConvertFromEUC();
+    void    onConvertFromJIS();
+    void    onConvertFromSJIS();
+    void    onConvertFromUTF8();
+    void    onConvertFromUTF16();
+    void    onConvertFromUTF16BE();
+    void    onConvertFromUTF16LE();
+    void    onCopy();
+    void    onScaleDown();
+    void    onScaleUp();
+    void    onSelectAll();
+
+    // QWidget interface
+public slots:
+    void setVisible(bool visible);
+
+protected:
+    void mousePressEvent(QMouseEvent *e);
+    void mouseDoubleClickEvent(QMouseEvent *e);
+    void mouseMoveEvent(QMouseEvent *e);
+    void paintEvent(QPaintEvent *e);
+    void resizeEvent(QResizeEvent *e);
+};
+
+#endif // TEXTVIEW_H
index b3bd27d..f5d5ada 100644 (file)
@@ -41,17 +41,17 @@ void ThumbnailView::initialize(MainWindow *w)
     viewport()->installEventFilter(w);
 }
 
-void ThumbnailView::scaleDown()
+void ThumbnailView::onScaleDown()
 {
-    qDebug() << "ThumbnailView::scaleDown()";
+    qDebug() << "ThumbnailView::onScaleDown()";
 
     static_cast<ThumbnailDelegate*>(itemDelegate())->scaleDown();
     folderModel()->clearPixmapCache();
 }
 
-void ThumbnailView::scaleUp()
+void ThumbnailView::onScaleUp()
 {
-    qDebug() << "ThumbnailView::scaleUp()";
+    qDebug() << "ThumbnailView::onScaleUp()";
 
     static_cast<ThumbnailDelegate*>(itemDelegate())->scaleUp();
     folderModel()->clearPixmapCache();
index c09fdd6..589edb3 100644 (file)
@@ -1,14 +1,13 @@
 #ifndef THUMBNAILVIEW_H
 #define THUMBNAILVIEW_H
 
-#include "abstractview.h"
 #include "folderview_private.h"
 #include "foldermodel.h"
 
 #include <QListView>
 class MainWindow;
 
-class ThumbnailView : public QListView, public AbstractView
+class ThumbnailView : public QListView
 {
     Q_OBJECT
 
@@ -24,11 +23,8 @@ private:
 signals:
 
 private slots:
-
-    // AbstractView interface
-public:
-    void scaleUp();
-    void scaleDown();
+    void onScaleUp();
+    void onScaleDown();
 
     // QAbstractItemView interface
 public: