summaryrefslogtreecommitdiffstats
path: root/gui/widgets
diff options
context:
space:
mode:
Diffstat (limited to 'gui/widgets')
-rw-r--r--gui/widgets/InstanceDelegate.cpp246
-rw-r--r--gui/widgets/InstanceDelegate.h27
-rw-r--r--gui/widgets/LabeledToolButton.cpp86
-rw-r--r--gui/widgets/LabeledToolButton.h37
-rw-r--r--gui/widgets/MCModInfoFrame.cpp111
-rw-r--r--gui/widgets/MCModInfoFrame.h46
-rw-r--r--gui/widgets/MCModInfoFrame.ui68
-rw-r--r--gui/widgets/ModListView.cpp51
-rw-r--r--gui/widgets/ModListView.h27
9 files changed, 699 insertions, 0 deletions
diff --git a/gui/widgets/InstanceDelegate.cpp b/gui/widgets/InstanceDelegate.cpp
new file mode 100644
index 00000000..487fed61
--- /dev/null
+++ b/gui/widgets/InstanceDelegate.cpp
@@ -0,0 +1,246 @@
+/* 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>
+
+// Origin: Qt
+static void viewItemTextLayout ( QTextLayout &textLayout, int lineWidth, qreal &height, qreal &widthUsed )
+{
+ height = 0;
+ widthUsed = 0;
+ textLayout.beginLayout();
+ QString str = textLayout.text();
+ while ( true )
+ {
+ QTextLine line = textLayout.createLine();
+ if ( !line.isValid() )
+ break;
+ if(line.textLength() == 0)
+ break;
+ line.setLineWidth ( lineWidth );
+ line.setPosition ( QPointF ( 0, height ) );
+ height += line.height();
+ widthUsed = qMax ( widthUsed, line.naturalTextWidth() );
+ }
+ textLayout.endLayout();
+}
+
+#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
+ {
+ 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;
+}
+
diff --git a/gui/widgets/InstanceDelegate.h b/gui/widgets/InstanceDelegate.h
new file mode 100644
index 00000000..6f924405
--- /dev/null
+++ b/gui/widgets/InstanceDelegate.h
@@ -0,0 +1,27 @@
+/* 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;
+};
diff --git a/gui/widgets/LabeledToolButton.cpp b/gui/widgets/LabeledToolButton.cpp
new file mode 100644
index 00000000..fe3cac45
--- /dev/null
+++ b/gui/widgets/LabeledToolButton.cpp
@@ -0,0 +1,86 @@
+/* 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 <QLabel>
+#include <QVBoxLayout>
+#include <QResizeEvent>
+#include <QStyleOption>
+#include "LabeledToolButton.h"
+#include <QApplication>
+
+/*
+ *
+ * Tool Button with a label on it, instead of the normal text rendering
+ *
+ */
+
+LabeledToolButton::LabeledToolButton(QWidget * parent)
+ : QToolButton(parent)
+ , m_label(new QLabel(this))
+{
+ //QToolButton::setText(" ");
+ m_label->setWordWrap(true);
+ m_label->setMouseTracking(false);
+ m_label->setAlignment(Qt::AlignCenter);
+ m_label->setTextInteractionFlags(Qt::NoTextInteraction);
+ // somehow, this makes word wrap work in the QLabel. yay.
+ m_label->setMinimumWidth(100);
+}
+
+QString LabeledToolButton::text() const
+{
+ return m_label->text();
+}
+
+void LabeledToolButton::setText(const QString & text)
+{
+ m_label->setText(text);
+}
+
+/*!
+ \reimp
+*/
+QSize LabeledToolButton::sizeHint() const
+{
+ /*
+ Q_D(const QToolButton);
+ if (d->sizeHint.isValid())
+ return d->sizeHint;
+ */
+ ensurePolished();
+
+ int w = 0, h = 0;
+ QStyleOptionToolButton opt;
+ initStyleOption(&opt);
+ QSize sz =m_label->sizeHint();
+ w = sz.width();
+ h = sz.height();
+
+ opt.rect.setSize(QSize(w, h)); // PM_MenuButtonIndicator depends on the height
+ if (popupMode() == MenuButtonPopup)
+ w += style()->pixelMetric(QStyle::PM_MenuButtonIndicator, &opt, this);
+
+ QSize rawSize = style()->sizeFromContents(QStyle::CT_ToolButton, &opt, QSize(w, h), this);
+ QSize sizeHint = rawSize.expandedTo(QApplication::globalStrut());
+ return sizeHint;
+}
+
+
+
+void LabeledToolButton::resizeEvent(QResizeEvent * event)
+{
+ m_label->setGeometry(QRect(4, 4, width()-8, height()-8));
+ QWidget::resizeEvent(event);
+}
diff --git a/gui/widgets/LabeledToolButton.h b/gui/widgets/LabeledToolButton.h
new file mode 100644
index 00000000..b417f814
--- /dev/null
+++ b/gui/widgets/LabeledToolButton.h
@@ -0,0 +1,37 @@
+/* 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 <QPushButton>
+#include <QToolButton>
+
+class QLabel;
+
+class LabeledToolButton : public QToolButton
+{
+ Q_OBJECT
+
+ QLabel * m_label;
+
+public:
+ LabeledToolButton(QWidget * parent = 0);
+
+ QString text() const;
+ void setText(const QString & text);
+ virtual QSize sizeHint() const;
+protected:
+ void resizeEvent(QResizeEvent * event);
+};
diff --git a/gui/widgets/MCModInfoFrame.cpp b/gui/widgets/MCModInfoFrame.cpp
new file mode 100644
index 00000000..ad167bc9
--- /dev/null
+++ b/gui/widgets/MCModInfoFrame.cpp
@@ -0,0 +1,111 @@
+/* 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 <QMessageBox>
+#include <QtGui>
+
+#include "MCModInfoFrame.h"
+#include "ui_MCModInfoFrame.h"
+#include "gui/dialogs/CustomMessageBox.h"
+
+void MCModInfoFrame::updateWithMod(Mod &m)
+{
+ if(m.type() == m.MOD_FOLDER)
+ {
+ clear();
+ return;
+ }
+
+ QString text = "";
+ QString name = "";
+ if(m.name().isEmpty()) name = m.id();
+ else name = m.name();
+
+ if(m.homeurl().isEmpty()) text = name;
+ else text = "<a href=\"" + m.homeurl() + "\">" + name + "</a>";
+ if(!m.authors().isEmpty()) text += " by " + m.authors();
+
+ setModText(text);
+
+ if(m.description().isEmpty())
+ {
+ setModDescription(tr("No description provided in mcmod.info"));
+ }
+ else
+ {
+ setModDescription(m.description());
+ }
+}
+
+void MCModInfoFrame::clear()
+{
+ setModText(tr("Select a mod to view title and authors..."));
+ setModDescription(tr("Select a mod to view description..."));
+}
+
+MCModInfoFrame::MCModInfoFrame(QWidget *parent) :
+ QFrame(parent),
+ ui(new Ui::MCModInfoFrame)
+{
+ ui->setupUi(this);
+}
+
+MCModInfoFrame::~MCModInfoFrame()
+{
+ delete ui;
+}
+
+void MCModInfoFrame::setModText(QString text)
+{
+ ui->label_ModText->setText(text);
+}
+
+void MCModInfoFrame::setModDescription(QString text)
+{
+ ui->label_ModDescription->setToolTip("");
+ QString intermediatetext = text.trimmed();
+ bool prev(false);
+ QChar rem('\n');
+ QString finaltext;
+ finaltext.reserve(intermediatetext.size());
+ foreach(const QChar& c, intermediatetext)
+ {
+ if(c == rem && prev){
+ continue;
+ }
+ prev = c == rem;
+ finaltext += c;
+ }
+ QString labeltext;
+ labeltext.reserve(300);
+ if(finaltext.length() > 290)
+ {
+ ui->label_ModDescription->setOpenExternalLinks(false);
+ ui->label_ModDescription->setTextFormat(Qt::TextFormat::RichText);
+ desc = text;
+ labeltext.append("<html><body>" + finaltext.left(287) + "<a href=\"#mod_desc\">...</a></body></html>");
+ QObject::connect(ui->label_ModDescription, &QLabel::linkActivated, this, &MCModInfoFrame::modDescEllipsisHandler);
+ }
+ else
+ {
+ ui->label_ModDescription->setTextFormat(Qt::TextFormat::PlainText);
+ labeltext.append(finaltext);
+ }
+ ui->label_ModDescription->setText(labeltext);
+}
+void MCModInfoFrame::modDescEllipsisHandler(const QString &link)
+{
+ CustomMessageBox::selectable(this, tr(""), desc)->show();
+}
diff --git a/gui/widgets/MCModInfoFrame.h b/gui/widgets/MCModInfoFrame.h
new file mode 100644
index 00000000..54c5d674
--- /dev/null
+++ b/gui/widgets/MCModInfoFrame.h
@@ -0,0 +1,46 @@
+/* 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 <QFrame>
+#include "logic/Mod.h"
+
+namespace Ui
+{
+class MCModInfoFrame;
+}
+
+class MCModInfoFrame : public QFrame
+{
+ Q_OBJECT
+
+public:
+ explicit MCModInfoFrame(QWidget *parent = 0);
+ ~MCModInfoFrame();
+
+ void setModText(QString text);
+ void setModDescription(QString text);
+
+ void updateWithMod(Mod &m);
+ void clear();
+
+public slots:
+ void modDescEllipsisHandler(const QString& link );
+
+private:
+ Ui::MCModInfoFrame *ui;
+ QString desc;
+};
diff --git a/gui/widgets/MCModInfoFrame.ui b/gui/widgets/MCModInfoFrame.ui
new file mode 100644
index 00000000..60e0a65c
--- /dev/null
+++ b/gui/widgets/MCModInfoFrame.ui
@@ -0,0 +1,68 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<ui version="4.0">
+ <class>MCModInfoFrame</class>
+ <widget class="QFrame" name="MCModInfoFrame">
+ <property name="geometry">
+ <rect>
+ <x>0</x>
+ <y>0</y>
+ <width>527</width>
+ <height>113</height>
+ </rect>
+ </property>
+ <property name="sizePolicy">
+ <sizepolicy hsizetype="Preferred" vsizetype="Minimum">
+ <horstretch>0</horstretch>
+ <verstretch>0</verstretch>
+ </sizepolicy>
+ </property>
+ <property name="maximumSize">
+ <size>
+ <width>16777215</width>
+ <height>120</height>
+ </size>
+ </property>
+ <property name="windowTitle">
+ <string>Frame</string>
+ </property>
+ <layout class="QVBoxLayout" name="verticalLayout_2">
+ <item>
+ <widget class="QLabel" name="label_ModText">
+ <property name="text">
+ <string>Select a mod to view title and authors...</string>
+ </property>
+ <property name="textFormat">
+ <enum>Qt::RichText</enum>
+ </property>
+ <property name="alignment">
+ <set>Qt::AlignLeading|Qt::AlignLeft|Qt::AlignTop</set>
+ </property>
+ <property name="wordWrap">
+ <bool>true</bool>
+ </property>
+ <property name="openExternalLinks">
+ <bool>true</bool>
+ </property>
+ </widget>
+ </item>
+ <item>
+ <widget class="QLabel" name="label_ModDescription">
+ <property name="text">
+ <string>Select a mod to view description...</string>
+ </property>
+ <property name="textFormat">
+ <enum>Qt::PlainText</enum>
+ </property>
+ <property name="alignment">
+ <set>Qt::AlignLeading|Qt::AlignLeft|Qt::AlignTop</set>
+ </property>
+ <property name="wordWrap">
+ <bool>true</bool>
+ </property>
+ </widget>
+ </item>
+ </layout>
+ </widget>
+ <resources/>
+ <connections/>
+</ui>
diff --git a/gui/widgets/ModListView.cpp b/gui/widgets/ModListView.cpp
new file mode 100644
index 00000000..838af75e
--- /dev/null
+++ b/gui/widgets/ModListView.cpp
@@ -0,0 +1,51 @@
+/* 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 "ModListView.h"
+#include <QHeaderView>
+#include <QMouseEvent>
+#include <QPainter>
+#include <QDrag>
+#include <QRect>
+
+ModListView::ModListView ( QWidget* parent )
+ :QTreeView ( parent )
+{
+ setAllColumnsShowFocus ( true );
+ setExpandsOnDoubleClick ( false );
+ setRootIsDecorated ( false );
+ setSortingEnabled ( false );
+ setAlternatingRowColors ( true );
+ setSelectionMode ( QAbstractItemView::ContiguousSelection );
+ setHeaderHidden ( false );
+ setSelectionBehavior(QAbstractItemView::SelectRows);
+ setVerticalScrollBarPolicy ( Qt::ScrollBarAlwaysOn );
+ setHorizontalScrollBarPolicy ( Qt::ScrollBarAsNeeded );
+ setDropIndicatorShown(true);
+ setDragEnabled(true);
+ setDragDropMode(QAbstractItemView::DropOnly);
+ viewport()->setAcceptDrops(true);
+}
+
+void ModListView::setModel ( QAbstractItemModel* model )
+{
+ QTreeView::setModel ( model );
+ auto head = header();
+ head->setStretchLastSection(false);
+ head->setSectionResizeMode(0, QHeaderView::Stretch);
+ for(int i = 1; i < head->count(); i++)
+ head->setSectionResizeMode(i, QHeaderView::ResizeToContents);
+ dropIndicatorPosition();
+}
diff --git a/gui/widgets/ModListView.h b/gui/widgets/ModListView.h
new file mode 100644
index 00000000..b26fa26b
--- /dev/null
+++ b/gui/widgets/ModListView.h
@@ -0,0 +1,27 @@
+/* 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 <QTreeView>
+
+class Mod;
+
+class ModListView: public QTreeView
+{
+ Q_OBJECT
+public:
+ explicit ModListView ( QWidget* parent = 0 );
+ virtual void setModel ( QAbstractItemModel* model );
+};