This commit is contained in:
Petr Mrázek 2014-02-04 01:40:51 +01:00
parent b82eb5873e
commit 7839c4ecc0
21 changed files with 41 additions and 514 deletions

View File

@ -186,7 +186,6 @@ configure_file("${PROJECT_SOURCE_DIR}/config.h.in" "${PROJECT_BINARY_DIR}/includ
ADD_DEFINITIONS(-DQUAZIP_STATIC)
ADD_DEFINITIONS(-DLIBSETTINGS_STATIC)
ADD_DEFINITIONS(-DLIBUTIL_STATIC)
ADD_DEFINITIONS(-DLIBGROUPVIEW_STATIC)
######## Packaging/install paths setup ########
@ -247,10 +246,6 @@ include_directories(${LIBUTIL_INCLUDE_DIR})
add_subdirectory(depends/settings)
include_directories(${LIBSETTINGS_INCLUDE_DIR})
# Add the group view library.
add_subdirectory(depends/groupview)
include_directories(${LIBGROUPVIEW_INCLUDE_DIR})
# Add the updater
add_subdirectory(mmc_updater)
@ -317,8 +312,6 @@ gui/dialogs/UpdateDialog.cpp
# GUI - widgets
gui/widgets/Common.h
gui/widgets/Common.cpp
gui/widgets/InstanceDelegate.h
gui/widgets/InstanceDelegate.cpp
gui/widgets/ModListView.h
gui/widgets/ModListView.cpp
gui/widgets/VersionListView.h
@ -328,6 +321,16 @@ gui/widgets/LabeledToolButton.cpp
gui/widgets/MCModInfoFrame.h
gui/widgets/MCModInfoFrame.cpp
# GUI - instance group view
gui/groupview/Group.cpp
gui/groupview/Group.h
gui/groupview/GroupedProxyModel.cpp
gui/groupview/GroupedProxyModel.h
gui/groupview/GroupView.cpp
gui/groupview/GroupView.h
gui/groupview/InstanceDelegate.cpp
gui/groupview/InstanceDelegate.h
# Base classes and infrastructure
logic/BaseVersion.h
logic/MinecraftVersion.h
@ -584,7 +587,7 @@ ADD_EXECUTABLE(MultiMC MACOSX_BUNDLE WIN32 main.cpp ${MULTIMC_RCS})
# Link
TARGET_LINK_LIBRARIES(MultiMC MultiMC_common)
TARGET_LINK_LIBRARIES(MultiMC_common xz-embedded unpack200 quazip libUtil libSettings libGroupView ${MultiMC_LINK_ADDITIONAL_LIBS})
TARGET_LINK_LIBRARIES(MultiMC_common xz-embedded unpack200 quazip libUtil libSettings ${MultiMC_LINK_ADDITIONAL_LIBS})
QT5_USE_MODULES(MultiMC Core Widgets Network Xml Concurrent ${MultiMC_QT_ADDITIONAL_MODULES})
QT5_USE_MODULES(MultiMC_common Core Widgets Network Xml Concurrent ${MultiMC_QT_ADDITIONAL_MODULES})

View File

@ -1,24 +0,0 @@
UseTab: true
IndentWidth: 4
TabWidth: 4
ConstructorInitializerIndentWidth: 4
AccessModifierOffset: -4
IndentCaseLabels: false
IndentFunctionDeclarationAfterType: false
NamespaceIndentation: None
BreakBeforeBraces: Allman
AllowShortIfStatementsOnASingleLine: false
ColumnLimit: 96
MaxEmptyLinesToKeep: 1
Standard: Cpp11
Cpp11BracedListStyle: true
SpacesInParentheses: false
SpaceInEmptyParentheses: false
SpacesInCStyleCastParentheses: false
SpaceAfterControlStatementKeyword: true
AlignTrailingComments: true
SpacesBeforeTrailingComments: 1

View File

@ -1,2 +0,0 @@
build/
*.user*

View File

@ -1,40 +0,0 @@
cmake_minimum_required(VERSION 2.8.9)
project(GroupView)
set(CMAKE_AUTOMOC ON)
IF(APPLE)
message(STATUS "Using APPLE CMAKE_CXX_FLAGS")
SET(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -std=c++11 -Wall")
ELSEIF(UNIX)
# assume GCC, add C++0x/C++11 stuff
MESSAGE(STATUS "Using UNIX CMAKE_CXX_FLAGS")
SET(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -std=c++11 -Wall")
ELSEIF(MINGW)
MESSAGE(STATUS "Using MINGW CMAKE_CXX_FLAGS")
SET(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -std=gnu++11 -Wall")
ENDIF()
find_package(Qt5Core REQUIRED)
find_package(Qt5Gui REQUIRED)
find_package(Qt5Widgets REQUIRED)
include_directories(${Qt5Core_INCLUDE_DIRS} ${Qt5Gui_INCLUDE_DIRS} ${Qt5Widgets_INCLUDE_DIRS})
set(SOURCES
main.cpp
main.h
GroupView.h
GroupView.cpp
Group.h
Group.cpp
GroupedProxyModel.h
GroupedProxyModel.cpp
InstanceDelegate.h
InstanceDelegate.cpp
)
add_executable(GroupView ${SOURCES})
qt5_use_modules(GroupView Core Gui Widgets)

View File

@ -1,98 +0,0 @@
#include "main.h"
#include <QApplication>
#include <QStandardItemModel>
#include <QPainter>
#include <QTime>
#include "GroupView.h"
#include "GroupedProxyModel.h"
#include "InstanceDelegate.h"
Progresser *progresser;
QPixmap icon(const Qt::GlobalColor color)
{
QPixmap p = QPixmap(32, 32);
p.fill(QColor(color));
return p;
}
QPixmap icon(const int number)
{
QPixmap p = icon(Qt::white);
QPainter painter(&p);
QFont font = painter.font();
font.setBold(true);
font.setPixelSize(28);
painter.setFont(font);
painter.drawText(QRect(QPoint(0, 0), p.size()), Qt::AlignVCenter | Qt::AlignHCenter,
QString::number(number));
painter.end();
return p;
}
QStandardItem *createItem(const Qt::GlobalColor color, const QString &text,
const QString &category)
{
QStandardItem *item = new QStandardItem;
item->setText(text);
item->setData(icon(color), Qt::DecorationRole);
item->setData(category, GroupViewRoles::GroupRole);
item->setFlags(Qt::ItemIsEnabled | Qt::ItemIsSelectable);
// progresser->addTrackedIndex(item);
return item;
}
QStandardItem *createItem(const int index, const QString &category)
{
QStandardItem *item = new QStandardItem;
item->setText(QString("Item #%1").arg(index));
item->setData(icon(index), Qt::DecorationRole);
item->setData(category, GroupViewRoles::GroupRole);
item->setFlags(Qt::ItemIsEnabled | Qt::ItemIsSelectable);
// progresser->addTrackedIndex(item);
return item;
}
int main(int argc, char *argv[])
{
QApplication a(argc, argv);
qsrand(QTime::currentTime().msec());
progresser = new Progresser();
QStandardItemModel model;
model.setRowCount(10);
model.setColumnCount(1);
model.setItem(
0, createItem(Qt::red,
"Red is a color. Some more text. I'm out of ideas. 42. What's your name?",
"Colorful"));
model.setItem(1, createItem(Qt::blue, "Blue", "Colorful"));
model.setItem(2, createItem(Qt::yellow, "Yellow", "Colorful"));
model.setItem(3, createItem(Qt::black, "Black", "Not Colorful"));
model.setItem(4, createItem(Qt::darkGray, "Dark Gray", "Not Colorful"));
model.setItem(5, createItem(Qt::gray, "Gray", "Not Colorful"));
model.setItem(6, createItem(Qt::lightGray, "Light Gray", "Not Colorful"));
model.setItem(7, createItem(Qt::white, "White", "Not Colorful"));
model.setItem(8, createItem(Qt::darkGreen, "Dark Green", ""));
model.setItem(9, progresser->addTrackedIndex(createItem(Qt::green, "Green", "")));
for (int i = 0; i < 20; ++i)
{
model.setItem(i + 10, createItem(i + 1, "Items 1-20"));
}
GroupedProxyModel pModel;
pModel.setSourceModel(&model);
GroupView w;
w.setItemDelegate(new ListViewDelegate);
w.setModel(&pModel);
w.resize(640, 480);
w.show();
return a.exec();
}

View File

@ -1,54 +0,0 @@
#pragma once
#include <QObject>
#include <QTimer>
#include <QList>
#include <QStandardItem>
#include <QDebug>
#include "GroupView.h"
class Progresser : public QObject
{
Q_OBJECT
public:
explicit Progresser(QObject *parent = 0) : QObject(parent)
{
QTimer *timer = new QTimer(this);
connect(timer, SIGNAL(timeout()), this, SLOT(timeout()));
timer->start(50);
}
QStandardItem *addTrackedIndex(QStandardItem *item)
{
item->setData(1000, GroupViewRoles::ProgressMaximumRole);
m_items.append(item);
return item;
}
public
slots:
void timeout()
{
QList<QStandardItem *> toRemove;
for (auto item : m_items)
{
int maximum = item->data(GroupViewRoles::ProgressMaximumRole).toInt();
int value = item->data(GroupViewRoles::ProgressValueRole).toInt();
int newvalue = std::min(value + 3, maximum);
item->setData(newvalue, GroupViewRoles::ProgressValueRole);
if(newvalue >= maximum)
{
toRemove.append(item);
}
}
for(auto remove : toRemove)
{
m_items.removeAll(remove);
}
}
private:
QList<QStandardItem *> m_items;
};

View File

@ -26,6 +26,7 @@
#include <QInputDialog>
#include <QDesktopServices>
#include <QKeyEvent>
#include <QUrl>
#include <QDir>
#include <QFileInfo>
@ -37,12 +38,12 @@
#include "userutils.h"
#include "pathutils.h"
#include "categorizedview.h"
#include "categorydrawer.h"
#include "gui/groupview/GroupView.h"
#include "gui/groupview/InstanceDelegate.h"
#include "gui/Platform.h"
#include "gui/widgets/InstanceDelegate.h"
#include "gui/widgets/LabeledToolButton.h"
#include "gui/dialogs/SettingsDialog.h"
@ -140,21 +141,21 @@ MainWindow::MainWindow(QWidget *parent) : QMainWindow(parent), ui(new Ui::MainWi
// Create the instance list widget
{
view = new KCategorizedView(ui->centralWidget);
drawer = new KCategoryDrawer(view);
view = new GroupView(ui->centralWidget);
view->setSelectionMode(QAbstractItemView::SingleSelection);
view->setCategoryDrawer(drawer);
view->setCollapsibleBlocks(true);
view->setViewMode(QListView::IconMode);
view->setFlow(QListView::LeftToRight);
view->setWordWrap(true);
view->setMouseTracking(true);
view->viewport()->setAttribute(Qt::WA_Hover);
// view->setCategoryDrawer(drawer);
// view->setCollapsibleBlocks(true);
// view->setViewMode(QListView::IconMode);
// view->setFlow(QListView::LeftToRight);
// view->setWordWrap(true);
// view->setMouseTracking(true);
// view->viewport()->setAttribute(Qt::WA_Hover);
auto delegate = new ListViewDelegate();
view->setItemDelegate(delegate);
view->setSpacing(10);
view->setUniformItemWidths(true);
// view->setSpacing(10);
// view->setUniformItemWidths(true);
// do not show ugly blue border on the mac
view->setAttribute(Qt::WA_MacShowFocusRect, false);
@ -331,7 +332,6 @@ MainWindow::~MainWindow()
{
delete ui;
delete proxymodel;
delete drawer;
}
void MainWindow::showInstanceContextMenu(const QPoint &pos)

View File

@ -27,9 +27,6 @@
class QToolButton;
class LabeledToolButton;
class QLabel;
class InstanceProxyModel;
class KCategorizedView;
class KCategoryDrawer;
class MinecraftProcess;
class ConsoleWindow;
@ -185,8 +182,7 @@ protected:
private:
Ui::MainWindow *ui;
KCategoryDrawer *drawer;
KCategorizedView *view;
class GroupView *view;
InstanceProxyModel *proxymodel;
MinecraftProcess *proc;
ConsoleWindow *console;

View File

@ -23,7 +23,7 @@
#include "ui_IconPickerDialog.h"
#include "gui/Platform.h"
#include "gui/widgets/InstanceDelegate.h"
#include "gui/groupview/InstanceDelegate.h"
#include "logic/icons/IconList.h"

View File

@ -12,10 +12,15 @@ bool GroupedProxyModel::lessThan(const QModelIndex &left, const QModelIndex &rig
const QString rightCategory = right.data(GroupViewRoles::GroupRole).toString();
if (leftCategory == rightCategory)
{
return left.row() < right.row();
return subSortLessThan(left, right);
}
else
{
return leftCategory < rightCategory;
}
}
bool GroupedProxyModel::subSortLessThan(const QModelIndex &left, const QModelIndex &right) const
{
return left.row() < right.row();
}

View File

@ -10,5 +10,6 @@ public:
GroupedProxyModel(QObject *parent = 0);
protected:
bool lessThan(const QModelIndex &left, const QModelIndex &right) const;
virtual bool lessThan(const QModelIndex &left, const QModelIndex &right) const override;
virtual bool subSortLessThan(const QModelIndex &left, const QModelIndex &right) const;
};

View File

@ -1,231 +0,0 @@
/* Copyright 2013 MultiMC Contributors
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#include "InstanceDelegate.h"
#include <QPainter>
#include <QTextOption>
#include <QTextLayout>
#include <QApplication>
#include <QtCore/qmath.h>
#include "Common.h"
#define QFIXED_MAX (INT_MAX / 256)
ListViewDelegate::ListViewDelegate(QObject *parent) : QStyledItemDelegate(parent)
{
}
void drawSelectionRect(QPainter *painter, const QStyleOptionViewItemV4 &option,
const QRect &rect)
{
if ((option.state & QStyle::State_Selected))
painter->fillRect(rect, option.palette.brush(QPalette::Highlight));
else
{
QColor backgroundColor = option.palette.color(QPalette::Background);
backgroundColor.setAlpha(160);
painter->fillRect(rect, QBrush(backgroundColor));
}
}
void drawFocusRect(QPainter *painter, const QStyleOptionViewItemV4 &option, const QRect &rect)
{
if (!(option.state & QStyle::State_HasFocus))
return;
QStyleOptionFocusRect opt;
opt.direction = option.direction;
opt.fontMetrics = option.fontMetrics;
opt.palette = option.palette;
opt.rect = rect;
// opt.state = option.state | QStyle::State_KeyboardFocusChange |
// QStyle::State_Item;
auto col = option.state & QStyle::State_Selected ? QPalette::Highlight : QPalette::Base;
opt.backgroundColor = option.palette.color(col);
// Apparently some widget styles expect this hint to not be set
painter->setRenderHint(QPainter::Antialiasing, false);
QStyle *style = option.widget ? option.widget->style() : QApplication::style();
style->drawPrimitive(QStyle::PE_FrameFocusRect, &opt, painter, option.widget);
painter->setRenderHint(QPainter::Antialiasing);
}
static QSize viewItemTextSize(const QStyleOptionViewItemV4 *option)
{
QStyle *style = option->widget ? option->widget->style() : QApplication::style();
QTextOption textOption;
textOption.setWrapMode(QTextOption::WrapAtWordBoundaryOrAnywhere);
QTextLayout textLayout;
textLayout.setTextOption(textOption);
textLayout.setFont(option->font);
textLayout.setText(option->text);
const int textMargin =
style->pixelMetric(QStyle::PM_FocusFrameHMargin, option, option->widget) + 1;
QRect bounds(0, 0, 100 - 2 * textMargin, 600);
qreal height = 0, widthUsed = 0;
viewItemTextLayout(textLayout, bounds.width(), height, widthUsed);
const QSize size(qCeil(widthUsed), qCeil(height));
return QSize(size.width() + 2 * textMargin, size.height());
}
void ListViewDelegate::paint(QPainter *painter, const QStyleOptionViewItem &option,
const QModelIndex &index) const
{
QStyleOptionViewItemV4 opt = option;
initStyleOption(&opt, index);
painter->save();
painter->setClipRect(opt.rect);
opt.features |= QStyleOptionViewItem::WrapText;
opt.text = index.data().toString();
opt.textElideMode = Qt::ElideRight;
opt.displayAlignment = Qt::AlignTop | Qt::AlignHCenter;
QStyle *style = opt.widget ? opt.widget->style() : QApplication::style();
// const int iconSize = style->pixelMetric(QStyle::PM_IconViewIconSize);
const int iconSize = 48;
QRect iconbox = opt.rect;
const int textMargin = style->pixelMetric(QStyle::PM_FocusFrameHMargin, 0, opt.widget) + 1;
QRect textRect = opt.rect;
QRect textHighlightRect = textRect;
// clip the decoration on top, remove width padding
textRect.adjust(textMargin, iconSize + textMargin + 5, -textMargin, 0);
textHighlightRect.adjust(0, iconSize + 5, 0, 0);
// draw background
{
// FIXME: unused
// QSize textSize = viewItemTextSize ( &opt );
QPalette::ColorGroup cg;
QStyleOptionViewItemV4 opt2(opt);
if ((opt.widget && opt.widget->isEnabled()) || (opt.state & QStyle::State_Enabled))
{
if (!(opt.state & QStyle::State_Active))
cg = QPalette::Inactive;
else
cg = QPalette::Normal;
}
else
{
cg = QPalette::Disabled;
}
opt2.palette.setCurrentColorGroup(cg);
// fill in background, if any
if (opt.backgroundBrush.style() != Qt::NoBrush)
{
QPointF oldBO = painter->brushOrigin();
painter->setBrushOrigin(opt.rect.topLeft());
painter->fillRect(opt.rect, opt.backgroundBrush);
painter->setBrushOrigin(oldBO);
}
if (opt.showDecorationSelected)
{
drawSelectionRect(painter, opt2, opt.rect);
drawFocusRect(painter, opt2, opt.rect);
// painter->fillRect ( opt.rect, opt.palette.brush ( cg, QPalette::Highlight ) );
}
else
{
// if ( opt.state & QStyle::State_Selected )
{
// QRect textRect = subElementRect ( QStyle::SE_ItemViewItemText, opt,
// opt.widget );
// painter->fillRect ( textHighlightRect, opt.palette.brush ( cg,
// QPalette::Highlight ) );
drawSelectionRect(painter, opt2, textHighlightRect);
drawFocusRect(painter, opt2, textHighlightRect);
}
}
}
// draw the icon
{
QIcon::Mode mode = QIcon::Normal;
if (!(opt.state & QStyle::State_Enabled))
mode = QIcon::Disabled;
else if (opt.state & QStyle::State_Selected)
mode = QIcon::Selected;
QIcon::State state = opt.state & QStyle::State_Open ? QIcon::On : QIcon::Off;
iconbox.setHeight(iconSize);
opt.icon.paint(painter, iconbox, Qt::AlignCenter, mode, state);
}
// set the text colors
QPalette::ColorGroup cg =
opt.state & QStyle::State_Enabled ? QPalette::Normal : QPalette::Disabled;
if (cg == QPalette::Normal && !(opt.state & QStyle::State_Active))
cg = QPalette::Inactive;
if (opt.state & QStyle::State_Selected)
{
painter->setPen(opt.palette.color(cg, QPalette::HighlightedText));
}
else
{
painter->setPen(opt.palette.color(cg, QPalette::Text));
}
// draw the text
QTextOption textOption;
textOption.setWrapMode(QTextOption::WrapAtWordBoundaryOrAnywhere);
textOption.setTextDirection(opt.direction);
textOption.setAlignment(QStyle::visualAlignment(opt.direction, opt.displayAlignment));
QTextLayout textLayout;
textLayout.setTextOption(textOption);
textLayout.setFont(opt.font);
textLayout.setText(opt.text);
qreal width, height;
viewItemTextLayout(textLayout, textRect.width(), height, width);
const int lineCount = textLayout.lineCount();
const QRect layoutRect = QStyle::alignedRect(
opt.direction, opt.displayAlignment, QSize(textRect.width(), int(height)), textRect);
const QPointF position = layoutRect.topLeft();
for (int i = 0; i < lineCount; ++i)
{
const QTextLine line = textLayout.lineAt(i);
line.draw(painter, position);
}
painter->restore();
}
QSize ListViewDelegate::sizeHint(const QStyleOptionViewItem &option,
const QModelIndex &index) const
{
QStyleOptionViewItemV4 opt = option;
initStyleOption(&opt, index);
opt.features |= QStyleOptionViewItem::WrapText;
opt.text = index.data().toString();
opt.textElideMode = Qt::ElideRight;
opt.displayAlignment = Qt::AlignTop | Qt::AlignHCenter;
QStyle *style = opt.widget ? opt.widget->style() : QApplication::style();
const int textMargin =
style->pixelMetric(QStyle::PM_FocusFrameHMargin, &option, opt.widget) + 1;
int height = 48 + textMargin * 2 + 5; // TODO: turn constants into variables
QSize szz = viewItemTextSize(&opt);
height += szz.height();
// FIXME: maybe the icon items could scale and keep proportions?
QSize sz(100, height);
return sz;
}

View File

@ -1,27 +0,0 @@
/* Copyright 2013 MultiMC Contributors
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#pragma once
#include <QStyledItemDelegate>
class ListViewDelegate : public QStyledItemDelegate
{
public:
explicit ListViewDelegate ( QObject* parent = 0 );
protected:
void paint ( QPainter* painter, const QStyleOptionViewItem& option, const QModelIndex& index ) const;
QSize sizeHint ( const QStyleOptionViewItem & option, const QModelIndex & index ) const;
};

View File

@ -33,6 +33,7 @@
#include "logic/BaseInstance.h"
#include "logic/InstanceFactory.h"
#include "logger/QsLog.h"
#include <gui/groupview/GroupView.h>
const static int GROUP_FILE_FORMAT_VERSION = 1;
@ -96,8 +97,7 @@ QVariant InstanceList::data(const QModelIndex &index, int role) const
return MMC->icons()->getIcon(key);
}
// for now.
case KCategorizedSortFilterProxyModel::CategorySortRole:
case KCategorizedSortFilterProxyModel::CategoryDisplayRole:
case GroupViewRoles::GroupRole:
{
return pdata->group();
}
@ -585,10 +585,8 @@ void InstanceList::propertiesChanged(BaseInstance *inst)
}
InstanceProxyModel::InstanceProxyModel(QObject *parent)
: KCategorizedSortFilterProxyModel(parent)
: GroupedProxyModel(parent)
{
// disable since by default we are globally sorting by date:
setCategorizedModel(true);
}
bool InstanceProxyModel::subSortLessThan(const QModelIndex &left,

View File

@ -18,7 +18,7 @@
#include <QObject>
#include <QAbstractListModel>
#include <QSet>
#include "categorizedsortfilterproxymodel.h"
#include <gui/groupview/GroupedProxyModel.h>
#include <QIcon>
#include "logic/BaseInstance.h"
@ -129,7 +129,7 @@ protected:
QSet<QString> m_groups;
};
class InstanceProxyModel : public KCategorizedSortFilterProxyModel
class InstanceProxyModel : public GroupedProxyModel
{
public:
explicit InstanceProxyModel(QObject *parent = 0);