bunch of stuff. very basic drag/drop now working

This commit is contained in:
Ikatono
2024-05-20 03:23:01 -05:00
commit fac2260a01
28 changed files with 1631 additions and 0 deletions

75
.gitignore vendored Normal file
View File

@@ -0,0 +1,75 @@
# This file is used to ignore files which are generated
# ----------------------------------------------------------------------------
*~
*.autosave
*.a
*.core
*.moc
*.o
*.obj
*.orig
*.rej
*.so
*.so.*
*_pch.h.cpp
*_resource.rc
*.qm
.#*
*.*#
core
!core/
tags
.DS_Store
.directory
*.debug
Makefile*
*.prl
*.app
moc_*.cpp
ui_*.h
qrc_*.cpp
Thumbs.db
*.res
*.rc
/.qmake.cache
/.qmake.stash
# qtcreator generated files
*.pro.user*
CMakeLists.txt.user*
# xemacs temporary files
*.flc
# Vim temporary files
.*.swp
# Visual Studio generated files
*.ib_pdb_index
*.idb
*.ilk
*.pdb
*.sln
*.suo
*.vcproj
*vcproj.*.*.user
*.ncb
*.sdf
*.opensdf
*.vcxproj
*vcxproj.*
# MinGW generated files
*.Debug
*.Release
# Python byte code
*.pyc
# Binaries
# --------
*.dll
*.exe
build

84
CMakeLists.txt Normal file
View File

@@ -0,0 +1,84 @@
cmake_minimum_required(VERSION 3.5)
project(qt-app VERSION 0.1 LANGUAGES CXX)
set(CMAKE_AUTOUIC ON)
set(CMAKE_AUTOMOC ON)
set(CMAKE_AUTORCC ON)
set(CMAKE_CXX_STANDARD 17)
set(CMAKE_CXX_STANDARD_REQUIRED ON)
find_package(QT NAMES Qt6 Qt5 REQUIRED COMPONENTS Widgets)
find_package(Qt${QT_VERSION_MAJOR} REQUIRED COMPONENTS Widgets)
find_package(Qt${QT_VERSION_MAJOR} REQUIRED COMPONENTS Network)
set(PROJECT_SOURCES
main.cpp
mainwindow.cpp
mainwindow.h
mainwindow.ui
)
if(${QT_VERSION_MAJOR} GREATER_EQUAL 6)
qt_add_executable(qt-app
MANUAL_FINALIZATION
${PROJECT_SOURCES}
tiercard.hpp tiercard.cpp
flowlayout.cpp flowlayout.h flowlayout.pro
tiercardlayout.hpp tiercardlayout.cpp
aspectratiopixmaplabel.hpp aspectratiopixmaplabel.cpp
fullsizelayout.hpp fullsizelayout.cpp
tierrow.hpp tierrow.cpp
tierrowtitlecard.hpp tierrowtitlecard.cpp
myflowlayout.hpp myflowlayout.cpp
utils.hpp
rowholder.hpp rowholder.cpp
settings.hpp settings.cpp
)
# Define target properties for Android with Qt 6 as:
# set_property(TARGET qt-app APPEND PROPERTY QT_ANDROID_PACKAGE_SOURCE_DIR
# ${CMAKE_CURRENT_SOURCE_DIR}/android)
# For more information, see https://doc.qt.io/qt-6/qt-add-executable.html#target-creation
else()
if(ANDROID)
add_library(qt-app SHARED
${PROJECT_SOURCES}
)
# Define properties for Android with Qt 5 after find_package() calls as:
# set(ANDROID_PACKAGE_SOURCE_DIR "${CMAKE_CURRENT_SOURCE_DIR}/android")
else()
add_executable(qt-app
${PROJECT_SOURCES}
)
endif()
endif()
target_link_libraries(qt-app PRIVATE Qt${QT_VERSION_MAJOR}::Widgets)
target_link_libraries(qt-app PRIVATE Qt${QT_VERISON_MAJOR}::Network)
# Qt for iOS sets MACOSX_BUNDLE_GUI_IDENTIFIER automatically since Qt 6.1.
# If you are developing for iOS or macOS you should consider setting an
# explicit, fixed bundle identifier manually though.
if(${QT_VERSION} VERSION_LESS 6.1.0)
set(BUNDLE_ID_OPTION MACOSX_BUNDLE_GUI_IDENTIFIER com.example.qt-app)
endif()
set_target_properties(qt-app PROPERTIES
${BUNDLE_ID_OPTION}
MACOSX_BUNDLE_BUNDLE_VERSION ${PROJECT_VERSION}
MACOSX_BUNDLE_SHORT_VERSION_STRING ${PROJECT_VERSION_MAJOR}.${PROJECT_VERSION_MINOR}
MACOSX_BUNDLE TRUE
WIN32_EXECUTABLE TRUE
)
include(GNUInstallDirs)
install(TARGETS qt-app
BUNDLE DESTINATION .
LIBRARY DESTINATION ${CMAKE_INSTALL_LIBDIR}
RUNTIME DESTINATION ${CMAKE_INSTALL_BINDIR}
)
if(QT_VERSION_MAJOR EQUAL 6)
qt_finalize_executable(qt-app)
endif()

View File

@@ -0,0 +1,36 @@
#include "aspectratiopixmaplabel.hpp"
AspectRatioPixmapLabel::AspectRatioPixmapLabel(QWidget *parent) :
QLabel(parent)
{
this->setMinimumSize(1,1);
setScaledContents(false);
}
void AspectRatioPixmapLabel::setPixmap ( const QPixmap & p)
{
pix = p;
QLabel::setPixmap(scaledPixmap());
}
int AspectRatioPixmapLabel::heightForWidth( int width ) const
{
return pix.isNull() ? this->height() : ((qreal)pix.height()*width)/pix.width();
}
QSize AspectRatioPixmapLabel::sizeHint() const
{
int w = this->width();
return QSize( w, heightForWidth(w) );
}
QPixmap AspectRatioPixmapLabel::scaledPixmap() const
{
return pix.scaled(this->size(), Qt::KeepAspectRatio, Qt::SmoothTransformation);
}
void AspectRatioPixmapLabel::resizeEvent(QResizeEvent * e)
{
if(!pix.isNull())
QLabel::setPixmap(scaledPixmap());
}

View File

@@ -0,0 +1,23 @@
#ifndef ASPECTRATIOPIXMAPLABEL_HPP
#define ASPECTRATIOPIXMAPLABEL_HPP
#include <QLabel>
#include <QPixmap>
#include <QResizeEvent>
class AspectRatioPixmapLabel : public QLabel
{
Q_OBJECT
public:
explicit AspectRatioPixmapLabel(QWidget *parent = 0);
virtual int heightForWidth( int width ) const;
virtual QSize sizeHint() const;
QPixmap scaledPixmap() const;
public slots:
void setPixmap ( const QPixmap & );
void resizeEvent(QResizeEvent *);
private:
QPixmap pix;
};
#endif // ASPECTRATIOPIXMAPLABEL_HPP

154
flowlayout.cpp Normal file
View File

@@ -0,0 +1,154 @@
// Copyright (C) 2016 The Qt Company Ltd.
// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR BSD-3-Clause
#include <QtWidgets>
#include "flowlayout.h"
//! [1]
FlowLayout::FlowLayout(QWidget *parent, int margin, int hSpacing, int vSpacing)
: QLayout(parent), m_hSpace(hSpacing), m_vSpace(vSpacing)
{
setContentsMargins(margin, margin, margin, margin);
}
FlowLayout::FlowLayout(int margin, int hSpacing, int vSpacing)
: m_hSpace(hSpacing), m_vSpace(vSpacing)
{
setContentsMargins(margin, margin, margin, margin);
}
FlowLayout::~FlowLayout()
{
for (auto& child : itemList)
{
delete child;
child = nullptr;
}
itemList.clear();
}
void FlowLayout::addItem(QLayoutItem *item)
{
itemList.append(item);
}
int FlowLayout::horizontalSpacing() const
{
if (m_hSpace >= 0) {
return m_hSpace;
} else {
return smartSpacing(QStyle::PM_LayoutHorizontalSpacing);
}
}
int FlowLayout::verticalSpacing() const
{
if (m_vSpace >= 0) {
return m_vSpace;
} else {
return smartSpacing(QStyle::PM_LayoutVerticalSpacing);
}
}
int FlowLayout::count() const
{
return itemList.size();
}
QLayoutItem *FlowLayout::itemAt(int index) const
{
return itemList.value(index);
}
QLayoutItem *FlowLayout::takeAt(int index)
{
if (index >= 0 && index < itemList.size())
return itemList.takeAt(index);
return nullptr;
}
Qt::Orientations FlowLayout::expandingDirections() const
{
return { };
}
bool FlowLayout::hasHeightForWidth() const
{
return true;
}
int FlowLayout::heightForWidth(int width) const
{
int height = doLayout(QRect(0, 0, width, 0), true);
return height;
}
void FlowLayout::setGeometry(const QRect &rect)
{
QLayout::setGeometry(rect);
doLayout(rect, false);
}
QSize FlowLayout::sizeHint() const
{
return minimumSize();
}
QSize FlowLayout::minimumSize() const
{
QSize size;
for (const QLayoutItem* item : std::as_const(itemList))
size = size.expandedTo(item->minimumSize());
const QMargins margins = contentsMargins();
size += QSize(margins.left() + margins.right(), margins.top() + margins.bottom());
return size;
}
int FlowLayout::doLayout(const QRect &rect, bool testOnly) const
{
int left, top, right, bottom;
getContentsMargins(&left, &top, &right, &bottom);
QRect effectiveRect = rect.adjusted(+left, +top, -right, -bottom);
int x = effectiveRect.x();
int y = effectiveRect.y();
int lineHeight = 0;
for (QLayoutItem* item : std::as_const(itemList)) {
const QWidget* wid = item->widget();
int spaceX = horizontalSpacing();
if (spaceX == -1)
spaceX = wid->style()->layoutSpacing(
QSizePolicy::PushButton, QSizePolicy::PushButton, Qt::Horizontal);
int spaceY = verticalSpacing();
if (spaceY == -1)
spaceY = wid->style()->layoutSpacing(
QSizePolicy::PushButton, QSizePolicy::PushButton, Qt::Vertical);
int nextX = x + item->sizeHint().width() + spaceX;
if (nextX - spaceX > effectiveRect.right() && lineHeight > 0) {
x = effectiveRect.x();
y = y + lineHeight + spaceY;
nextX = x + item->sizeHint().width() + spaceX;
lineHeight = 0;
}
if (!testOnly)
item->setGeometry(QRect(QPoint(x, y), item->sizeHint()));
x = nextX;
lineHeight = qMax(lineHeight, item->sizeHint().height());
}
return y + lineHeight - rect.y() + bottom;
}
int FlowLayout::smartSpacing(QStyle::PixelMetric pm) const
{
QObject* parent = this->parent();
if (!parent) {
return -1;
} else if (parent->isWidgetType()) {
QWidget* pw = static_cast<QWidget *>(parent);
return pw->style()->pixelMetric(pm, nullptr, pw);
} else {
return static_cast<QLayout*>(parent)->spacing();
}
}

41
flowlayout.h Normal file
View File

@@ -0,0 +1,41 @@
// Copyright (C) 2016 The Qt Company Ltd.
// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR BSD-3-Clause
#ifndef FLOWLAYOUT_H
#define FLOWLAYOUT_H
#include <QLayout>
#include <QRect>
#include <QStyle>
//! [0]
class FlowLayout : public QLayout
{
public:
explicit FlowLayout(QWidget *parent, int margin = -1, int hSpacing = -1, int vSpacing = -1);
explicit FlowLayout(int margin = -1, int hSpacing = -1, int vSpacing = -1);
~FlowLayout();
void addItem(QLayoutItem *item) override;
int horizontalSpacing() const;
int verticalSpacing() const;
Qt::Orientations expandingDirections() const override;
bool hasHeightForWidth() const override;
int heightForWidth(int) const override;
int count() const override;
QLayoutItem *itemAt(int index) const override;
QSize minimumSize() const override;
void setGeometry(const QRect &rect) override;
QSize sizeHint() const override;
QLayoutItem *takeAt(int index) override;
private:
int doLayout(const QRect &rect, bool testOnly) const;
int smartSpacing(QStyle::PixelMetric pm) const;
QList<QLayoutItem *> itemList;
int m_hSpace;
int m_vSpace;
};
//! [0]
#endif // FLOWLAYOUT_H

11
flowlayout.pro Normal file
View File

@@ -0,0 +1,11 @@
QT += widgets
HEADERS = flowlayout.h \
window.h
SOURCES = flowlayout.cpp \
main.cpp \
window.cpp
# install
target.path = $$[QT_INSTALL_EXAMPLES]/widgets/layouts/flowlayout
INSTALLS += target

91
fullsizelayout.cpp Normal file
View File

@@ -0,0 +1,91 @@
#include "fullsizelayout.hpp"
#include "qdebug.h"
#include "qwidget.h"
#include <algorithm>
FullSizeLayout::FullSizeLayout() {}
FullSizeLayout::~FullSizeLayout()
{
for (auto& child : itemList)
{
delete child;
child = nullptr;
}
itemList.clear();
}
void FullSizeLayout::addItem(QLayoutItem* item)
{
itemList.append(item);
}
int FullSizeLayout::horizontalSpacing() const
{
return 0;
}
int FullSizeLayout::verticalSpacing() const
{
return 0;
}
Qt::Orientations FullSizeLayout::expandingDirections() const
{
return Qt::Vertical | Qt::Horizontal;
}
bool FullSizeLayout::hasHeightForWidth() const
{
for (auto child : itemList)
{
if (child->hasHeightForWidth())
return true;
}
return false;
}
int FullSizeLayout::heightForWidth(int width) const
{
int h = -1;
for (auto child : itemList)
{
h = std::max(h, child->heightForWidth(width));
}
return h;
}
int FullSizeLayout::count() const
{
return static_cast<int>(itemList.count());
}
QLayoutItem* FullSizeLayout::itemAt(int index) const
{
return itemList.value(index);
}
QSize FullSizeLayout::minimumSize() const
{
QSize size;
for (auto child : itemList)
{
// auto wid = child->widget();
if (std::max(child->minimumSize().height(), child->minimumSize().width()) >= 200)
child->minimumSize();
// if (wid)
size = size.expandedTo(child->minimumSize());
}
return size;
}
void FullSizeLayout::setGeometry(const QRect &rect)
{
for (auto child : itemList)
{
child->setGeometry(rect);
}
}
QSize FullSizeLayout::sizeHint() const
{
QSize size(1,1);
for (auto child : itemList)
{
size = size.expandedTo(child->sizeHint());
}
return size;
}
QLayoutItem* FullSizeLayout::takeAt(int index)
{
return itemList.takeAt(index);
}

28
fullsizelayout.hpp Normal file
View File

@@ -0,0 +1,28 @@
#ifndef FULLSIZELAYOUT_HPP
#define FULLSIZELAYOUT_HPP
#include <QLayout>
class FullSizeLayout : public QLayout
{
public:
FullSizeLayout();
~FullSizeLayout();
void addItem(QLayoutItem *item) override;
int horizontalSpacing() const;
int verticalSpacing() const;
Qt::Orientations expandingDirections() const override;
bool hasHeightForWidth() const override;
int heightForWidth(int) const override;
int count() const override;
QLayoutItem *itemAt(int index) const override;
QSize minimumSize() const override;
void setGeometry(const QRect &rect) override;
QSize sizeHint() const override;
QLayoutItem *takeAt(int index) override;
private:
QList<QLayoutItem*> itemList;
};
#endif // FULLSIZELAYOUT_HPP

141
main.cpp Normal file
View File

@@ -0,0 +1,141 @@
#include "mainwindow.h"
#include "tiercard.hpp"
#include "tierrow.hpp"
#include "tiercardlayout.hpp"
#include "utils.hpp"
#include "rowholder.hpp"
#include <QApplication>
#include <QNetworkAccessManager>
#include <QNetworkReply>
#include <QImageReader>
#include <QTimer>
#include <QDockWidget>
#include <QScrollArea>
// int main(int argc, char *argv[])
// {
// QApplication a(argc, argv);
// // MainWindow w;
// // w.show();
// TierCard card;
// // card.setGeometry(0, 0, 200, 200);
// card.setFixedSize(200, 200);
// card.set_text("SOME TEXT");
// card.set_bg_color(QColor(255, 255, 255));
// card.show();
// QNetworkAccessManager qnam;
// QNetworkRequest req(QUrl("https://upload.wikimedia.org/wikipedia/en/4/4d/Shrek_%28character%29.png"));
// auto resp = qnam.get(req);
// QObject::connect(resp, &QNetworkReply::finished, [&card, resp]()
// {
// QImageReader reader(resp);
// reader.setAutoDetectImageFormat(true);
// QPixmap image = QPixmap::fromImageReader(&reader);
// card.set_image(image);
// });
// int fontSize = 10;
// QColor bg_switcher(255, 128, 128);
// QTimer bg_changer;
// bg_changer.setTimerType(Qt::PreciseTimer);
// bg_changer.setSingleShot(false);
// bg_changer.setInterval(1000);
// QObject::connect(&bg_changer, &QTimer::timeout, [&card, &bg_switcher, &fontSize, &a]()
// {
// card.set_bg_color(bg_switcher);
// a.setStyleSheet(QString("*[cssClass=\"tierCardText\"]{font-size: %1pt}").arg(fontSize));
// bg_switcher = QColor(bg_switcher.green(), bg_switcher.blue(), bg_switcher.red());
// fontSize+=3;
// });
// bg_changer.start();
// return a.exec();
// }
int main(int argc, char *argv[])
{
QApplication a(argc, argv);
MainWindow w;
// QDockWidget dock;
QScrollArea scroll;
TierRow* row = TierRow::create();
row->setColor(QColor(255, 128, 64));
row->setText("Row Title");
TierCard* card1 = TierCard::create();
row->setStyleSheet(makeBgColorString(QColor(35,35,35)));
card1->setText("CARD1");
card1->setBgColor(QColor(64,255,64));
card1->setFixedSize(150,150);
TierCard* card2 = TierCard::create();
card2->setText("CARD2");
card2->setBgColor(QColor(64,64,255));
card2->setFixedSize(150,150);
row->addCard(card1);
row->addCard(card2);
TierRow* row2 = TierRow::create();
row2->setColor(QColor(128, 128, 255));
row2->setText("Row Title");
TierCard* card3 = TierCard::create();
card3->setText("CARD1");
card3->setBgColor(QColor(64,12,164));
card3->setFixedSize(150,150);
TierCard* card4 = TierCard::create();
card4->setText("CARD2");
card4->setBgColor(QColor(164,64,155));
card4->setFixedSize(150,150);
auto card5 = TierCard::clone(card4);
card5->setFixedSize(150,150);
row->addCard(card5);
row2->addCard(card3);
row2->addCard(card4);
// row.show();
RowHolder holder;
holder.setSizePolicy(QSizePolicy::Ignored, QSizePolicy::Fixed);
// auto holderLayout = new QVBoxLayout();
holder.addRow(row);
holder.addRow(row2);
scroll.setWidget(&holder);
scroll.setWidgetResizable(true);
// dock.setWidget(&scroll);
// w.dockWidgetArea(&dock);
w.setCentralWidget(&scroll);
w.show();
w.setStyleSheet(a.styleSheet()
.append("#tierCardText {"
" font-style: bold;"
" font-size: 52; }")
.append("#tierCardId {"
" font-size: 24; }"));
// a.setFont()
// QTimer bg_changer;
// bg_changer.setTimerType(Qt::PreciseTimer);
// bg_changer.setSingleShot(false);
// bg_changer.setInterval(1000);
// QObject::connect(&bg_changer, &QTimer::timeout, [&row]()
// {
// row.updateGeometry();
// });
// bg_changer.start();
// w.show();
// callOnMeAndChildren<TierRow>(&row, [](TierRow* obj)
// {
// auto wid = dynamic_cast<QWidget*>(obj);
// if (wid)
// {
// auto size = wid->minimumSize();
// if (std::max(size.height(), size.width()) >= 200)
// {
// qDebug() << wid->objectName() << ": " << size;
// }
// }
// });
// qDebug() << row.minimumSize() << row.layout()->minimumSize();
return a.exec();
}

15
mainwindow.cpp Normal file
View File

@@ -0,0 +1,15 @@
#include "mainwindow.h"
#include "./ui_mainwindow.h"
MainWindow::MainWindow(QWidget *parent)
: QMainWindow(parent)
, ui(new Ui::MainWindow)
{
ui->setupUi(this);
}
MainWindow::~MainWindow()
{
delete ui;
ui = nullptr;
}

23
mainwindow.h Normal file
View File

@@ -0,0 +1,23 @@
#ifndef MAINWINDOW_H
#define MAINWINDOW_H
#include <QMainWindow>
QT_BEGIN_NAMESPACE
namespace Ui {
class MainWindow;
}
QT_END_NAMESPACE
class MainWindow : public QMainWindow
{
Q_OBJECT
public:
MainWindow(QWidget *parent = nullptr);
~MainWindow();
private:
Ui::MainWindow *ui;
};
#endif // MAINWINDOW_H

31
mainwindow.ui Normal file
View File

@@ -0,0 +1,31 @@
<?xml version="1.0" encoding="UTF-8"?>
<ui version="4.0">
<class>MainWindow</class>
<widget class="QMainWindow" name="MainWindow">
<property name="geometry">
<rect>
<x>0</x>
<y>0</y>
<width>800</width>
<height>600</height>
</rect>
</property>
<property name="windowTitle">
<string>MainWindow</string>
</property>
<widget class="QWidget" name="centralwidget"/>
<widget class="QMenuBar" name="menubar">
<property name="geometry">
<rect>
<x>0</x>
<y>0</y>
<width>800</width>
<height>25</height>
</rect>
</property>
</widget>
<widget class="QStatusBar" name="statusbar"/>
</widget>
<resources/>
<connections/>
</ui>

109
myflowlayout.cpp Normal file
View File

@@ -0,0 +1,109 @@
// #include "myflowlayout.hpp"
// #include "qexception.h"
// #include "qwidget.h"
// MyFlowLayout::MyFlowLayout(QWidget *parent, int margin, int hSpacing, int vSpacing)
// : QLayout(parent), hSpace(hSpacing), vSpace(vSpacing)
// {
// }
// MyFlowLayout::MyFlowLayout(int margin, int hSpacing, int vSpacing)
// : hSpace(hSpacing), vSpace(vSpacing)
// {
// }
// MyFlowLayout::~MyFlowLayout()
// {
// for (auto child : itemList)
// {
// delete child;
// }
// }
// void MyFlowLayout::addItem(QLayoutItem* item)
// {
// itemList.append(item);
// }
// int MyFlowLayout::horizontalSpacing() const
// {
// return hSpace;
// }
// int MyFlowLayout::verticalSpacing() const
// {
// return vSpace;
// }
// Qt::Orientations MyFlowLayout::expandingDirections() const
// {
// return { };
// }
// bool MyFlowLayout::hasHeightForWidth() const
// {
// return true;
// }
// int MyFlowLayout::heightForWidth(int width) const
// {
// QRect rect(0, 0, width, 0);
// return doLayout(rect, false);
// }
// QSize MyFlowLayout::minimumSize() const
// {
// QSize size(1,1);
// for (auto child : itemList)
// {
// size = size.expandedTo(child->minimumSize());
// }
// return size;
// }
// QLayoutItem* MyFlowLayout::itemAt(int index) const
// {
// return itemList.at(index);
// }
// QLayoutItem* MyFlowLayout::takeAt(int index)
// {
// return itemList.takeAt(index);
// }
// int MyFlowLayout::doLayout(const QRect &rect, bool apply) const
// {
// int left, top, right, bottom;
// getContentsMargins(&left, &top, &right, &bottom);
// QRect effectiveRect = rect.adjusted(+left, +top, -right, -bottom);
// int x = effectiveRect.x();
// int y = effectiveRect.y();
// int lineHeight = 0;
// for (QLayoutItem *item : std::as_const(itemList)) {
// const QWidget *wid = item->widget();
// int spaceX = horizontalSpacing();
// if (spaceX == -1)
// spaceX = wid->style()->layoutSpacing(
// QSizePolicy::PushButton, QSizePolicy::PushButton, Qt::Horizontal);
// int spaceY = verticalSpacing();
// if (spaceY == -1)
// spaceY = wid->style()->layoutSpacing(
// QSizePolicy::PushButton, QSizePolicy::PushButton, Qt::Vertical);
// int nextX = x + item->sizeHint().width() + spaceX;
// if (nextX - spaceX > effectiveRect.right() && lineHeight > 0) {
// x = effectiveRect.x();
// y = y + lineHeight + spaceY;
// nextX = x + item->sizeHint().width() + spaceX;
// lineHeight = 0;
// }
// if (apply)
// item->setGeometry(QRect(QPoint(x, y), item->sizeHint()));
// x = nextX;
// lineHeight = qMax(lineHeight, item->sizeHint().height());
// }
// return y + lineHeight - rect.y() + bottom;
// }

36
myflowlayout.hpp Normal file
View File

@@ -0,0 +1,36 @@
// #ifndef MYFLOWLAYOUT_HPP
// #define MYFLOWLAYOUT_HPP
// #include <QLayout>
// #include <QStyle>
// class MyFlowLayout : public QLayout
// {
// public:
// explicit MyFlowLayout(QWidget *parent, int margin = -1, int hSpacing = -1, int vSpacing = -1);
// explicit MyFlowLayout(int margin = -1, int hSpacing = -1, int vSpacing = -1);
// ~MyFlowLayout();
// void addItem(QLayoutItem *item) override;
// int horizontalSpacing() const;
// int verticalSpacing() const;
// Qt::Orientations expandingDirections() const override;
// bool hasHeightForWidth() const override;
// int heightForWidth(int width) const override;
// int count() const override;
// QLayoutItem* itemAt(int index) const override;
// QSize minimumSize() const override;
// void setGeometry(const QRect &rect) override;
// QSize sizeHint() const override;
// QLayoutItem* takeAt(int index) override;
// private:
// int doLayout(const QRect &rect, bool apply=true) const;
// int smartSpacing(QStyle::PixelMetric pm) const;
// QList<QLayoutItem *> itemList;
// int hSpace;
// int vSpace;
// };
// #endif // MYFLOWLAYOUT_HPP

19
rowholder.cpp Normal file
View File

@@ -0,0 +1,19 @@
#include "rowholder.hpp"
RowHolder::RowHolder()
{
_layout = new QVBoxLayout();
_layout->setAlignment(Qt::AlignTop);
setLayout(_layout);
}
void RowHolder::addRow(TierRow* row)
{
row->setSizePolicy(QSizePolicy::Ignored, QSizePolicy::Fixed);
_layout->addWidget(row, 0, Qt::AlignTop);
}
RowHolder::~RowHolder()
{
}

25
rowholder.hpp Normal file
View File

@@ -0,0 +1,25 @@
#ifndef ROWHOLDER_HPP
#define ROWHOLDER_HPP
#include "tierrow.hpp"
#include <QFrame>
#include <QObject>
#include <QWidget>
#include <QVBoxLayout>
class RowHolder : public QFrame
{
Q_OBJECT
public:
using IdType = uint32_t;
RowHolder();
~RowHolder();
void addRow(TierRow* row);
private:
QVBoxLayout* _layout;
};
#endif // ROWHOLDER_HPP

5
settings.cpp Normal file
View File

@@ -0,0 +1,5 @@
#include "settings.hpp"
Settings::Settings(QObject *parent)
: QObject{parent}
{}

15
settings.hpp Normal file
View File

@@ -0,0 +1,15 @@
#ifndef SETTINGS_HPP
#define SETTINGS_HPP
#include <QObject>
class Settings : public QObject
{
Q_OBJECT
public:
explicit Settings(QObject *parent = nullptr);
signals:
};
#endif // SETTINGS_HPP

185
tiercard.cpp Normal file
View File

@@ -0,0 +1,185 @@
#include "tiercard.hpp"
#include "fullsizelayout.hpp"
#include "qmimedata.h"
#include "utils.hpp"
#include <QVBoxLayout>
// TierCard::TierCard(QWidget *parent)
// : QWidget{parent}
// {
// auto bg_layout= new QVBoxLayout(this);
// bg_layout->setSpacing(0);
// bg_layout->setContentsMargins(0, 0, 0, 0);
// background = new QWidget();
// bg_layout->addWidget(background);
// auto img_layout = new QVBoxLayout(background);
// img_layout->setSpacing(0);
// img_layout->setContentsMargins(0, 0, 0, 0);
// image = new AspectRatioPixmapLabel();
// img_layout->addWidget(image, 0, Qt::AlignCenter);
// image->setAttribute(Qt::WA_TranslucentBackground);
// image->setAlignment(Qt::AlignCenter);
// auto txt_layout = new QVBoxLayout(image);
// txt_layout->setSpacing(0);
// txt_layout->setContentsMargins(0, 0, 0, 0);
// text_label = new QLabel();
// id_label = new QLabel("4");
// text_label->setWordWrap(true);
// // text_label->setTextFormat(Qt::RichText);
// text_label->setAlignment(Qt::AlignHCenter | Qt::AlignTop);
// id_label->setAlignment(Qt::AlignLeft | Qt::AlignBottom);
// text_label->setAttribute(Qt::WA_TranslucentBackground);
// id_label->setAttribute(Qt::WA_TranslucentBackground);
// txt_layout->addWidget(text_label, Qt::AlignTop | Qt::AlignHCenter);
// txt_layout->addWidget(id_label, Qt::AlignBottom, Qt::AlignLeft);
// text_label->setProperty("cssClass", "tierCardText");
// id_label->setProperty("cssClass", "tierCardId");
// }
TierCard::IdType TierCard::getAvailableId()
{
for (IdType id = 1;; id++)
{
if (idMap.find(id) == idMap.end())
{
return id;
}
}
}
void TierCard::releaseId(IdType id)
{
if (idMap.erase(id) == 0)
{
qDebug() << "Card id not found during destructor";
}
}
TierCard* TierCard::create(QWidget* parent)
{
TierCard* card;
auto id = getAvailableId();
card = new TierCard(id, parent);
idMap[id] = card;
return card;
}
TierCard* TierCard::clone(TierCard *other, QWidget* parent)
{
TierCard* card;
auto id = getAvailableId();
card = new TierCard(id, parent);
card->setText(other->getText());
auto img = other->getImage();
card->setImage(img);
card->setBgColor(other->getBgColor());
idMap[id] = card;
return card;
}
TierCard::TierCard(IdType id, QWidget* parent)
: QWidget{parent}
{
background = new QWidget();
image = new AspectRatioPixmapLabel();
image->setAttribute(Qt::WA_TranslucentBackground);
image->setAlignment(Qt::AlignCenter);
textLabel = new QLabel();
idLabel = new QLabel();
textLabel->setWordWrap(true);
// text_label->setTextFormat(Qt::RichText);
textLabel->setAlignment(Qt::AlignHCenter | Qt::AlignTop);
idLabel->setAlignment(Qt::AlignLeft | Qt::AlignBottom);
textLabel->setAttribute(Qt::WA_TranslucentBackground);
idLabel->setAttribute(Qt::WA_TranslucentBackground);
textLabel->setObjectName("tierCardText");
idLabel->setObjectName("tierCardId");
idLabel->setText(QString::number(id));
auto layout = new FullSizeLayout();
layout->addWidget(background);
layout->addWidget(image);
layout->addWidget(textLabel);
layout->addWidget(idLabel);
this->setLayout(layout);
}
TierCard::~TierCard()
{
releaseId(getId());
// delete text_label;
// text_label = nullptr;
// delete id_label;
// id_label = nullptr;
}
void TierCard::setText(QString str)
{
textLabel->setText(str);
}
QString TierCard::getText() const
{
return textLabel->text();
}
uint32_t TierCard::getId() const
{
return static_cast<uint32_t>(idLabel->text().toUInt());
}
void TierCard::setBgColor(QColor color)
{
bgColor = color;
auto str = makeBgColorString(color);
background->setStyleSheet(str);
}
QColor TierCard::getBgColor()
{
return bgColor;
}
void TierCard::setImage(const QPixmap img)
{
// QMetaObject::invokeMethod()
image->setPixmap(img);
}
QPixmap TierCard::getImage() const
{
return image->pixmap();
}
void TierCard::mousePressEvent(QMouseEvent* event)
{
qDebug() << "mouse press event";
QPixmap pix(size());
render(&pix);
QDrag drag(this);
drag.setPixmap(pix);
QByteArray itemData;
QDataStream dataStream(&itemData, QIODevice::WriteOnly);
auto _id = getId();
dataStream.writeRawData(reinterpret_cast<char*>(&_id), sizeof(_id));
QMimeData *mimeData = new QMimeData;
mimeData->setData(MimeType, itemData);
drag.setMimeData(mimeData);
hide();
if (drag.exec() == Qt::MoveAction)
{
show();
}
else
{
show();
}
}
TierCard* TierCard::getFromId(IdType id)
{
auto iter = idMap.find(id);
if (iter == idMap.end())
return nullptr;
return &(*iter->second);
}

49
tiercard.hpp Normal file
View File

@@ -0,0 +1,49 @@
#ifndef TIERCARD_H
#define TIERCARD_H
#include "aspectratiopixmaplabel.hpp"
#include <QWidget>
#include <QLabel>
#include <QColor>
#include <unordered_map>
class TierCard : public QWidget
{
Q_OBJECT
public:
using IdType = uint32_t;
inline static const char* MimeType = "application/x-tiercard";
TierCard(TierCard const&) = delete;
~TierCard();
static TierCard* create(QWidget *parent = nullptr);
static TierCard* clone(TierCard *other, QWidget* parent = nullptr);
static TierCard* getFromId(IdType id);
void setText(QString str);
QString getText() const;
void setImage(const QPixmap img);
QPixmap getImage() const;
IdType getId() const;
void setBgColor(QColor color);
QColor getBgColor();
// QColor bg_color() const;
protected:
void mousePressEvent(QMouseEvent* event);
private:
explicit TierCard(IdType id, QWidget *parent = nullptr);
QWidget* background;
AspectRatioPixmapLabel* image;
QLabel* textLabel;
QLabel* idLabel;
QColor bgColor;
static IdType getAvailableId();
static void releaseId(IdType id);
inline static std::unordered_map<IdType, TierCard*> idMap;
signals:
};
#endif // TIERCARD_H

30
tiercardlayout.cpp Normal file
View File

@@ -0,0 +1,30 @@
// #include "tiercardlayout.hpp"
// #include <QException>
// TierCardLayout::TierCardLayout()
// {
// // itemList.append(nullptr);
// // itemList.append(nullptr);
// // itemList.append(nullptr);
// }
// TierCardLayout::~TierCardLayout()
// {
// // QLayoutItem *item;
// // while ((item = takeAt(0)))
// // delete item;
// delete image;
// delete text;
// delete id;
// }
// void TierCardLayout::addItem(QLayoutItem *item)
// {
// // itemList.append(item);
// throw new QException();
// }
// QLayoutItem* TierCardLayout::itemAt(int index) const
// {
// throw new QException();
// }

31
tiercardlayout.hpp Normal file
View File

@@ -0,0 +1,31 @@
// #ifndef TIERCARDLAYOUT_HPP
// #define TIERCARDLAYOUT_HPP
// #include <QLayout>
// #include <QLabel>
// class TierCardLayout : public QLayout
// {
// public:
// TierCardLayout();
// ~TierCardLayout();
// void addItem(QLayoutItem *item) override;
// Qt::Orientations expandingDirections() const override;
// bool hasHeightForWidth() const override;
// int heightForWidth(int) const override;
// int count() const override;
// QLayoutItem *itemAt(int index) const override;
// QSize minimumSize() const override;
// void setGeometry(const QRect &rect) override;
// QSize sizeHint() const override;
// QLayoutItem *takeAt(int index) override;
// public
// private:
// QList<QLayoutItem *> itemList;
// QLabel* image;
// QLabel* text;
// QLabel* id;
// };
// #endif // TIERCARDLAYOUT_HPP

198
tierrow.cpp Normal file
View File

@@ -0,0 +1,198 @@
#include "tierrow.hpp"
#include "fullsizelayout.hpp"
#include "qmimedata.h"
#include "utils.hpp"
#include <QHBoxLayout>
TierRow::TierRow(IdType id, QWidget *parent)
: QWidget{parent}
{
setAcceptDrops(true);
auto fadeLayout = new FullSizeLayout();
fadeLayout->setSizeConstraint(QLayout::SetMinimumSize);
fadeLayout->setContentsMargins(0, 0, 0, 0);
fadeLayout->setSpacing(0);
bgFadeContainer = new QWidget();
bgFadeContainer->setStyleSheet(makeBgColorString(QColor(255,255,255,100)));
bgFadeContainer->setMinimumSize(0, 0);
fadeLayout->addWidget(bgFadeContainer);
this->setLayout(fadeLayout);
auto splitLayout = new QHBoxLayout();
splitLayout->setSizeConstraint(QLayout::SetMinimumSize);
splitLayout->setContentsMargins(0, 0, 0, 0);
splitLayout->setSpacing(0);
titleCard = new TierRowTitleCard(id);
cardContainer = new QWidget();
cardContainer->setMinimumSize(0, 0);
titleCard->setFixedSize(150, 150);
cardContainer->setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Fixed);
splitLayout->addWidget(titleCard, 0, Qt::AlignLeft | Qt::AlignTop);
splitLayout->addWidget(cardContainer, 1, Qt::AlignTop);
cardContainer->setStyleSheet(makeBgColorString(QColor(60,60,60,100)));
bgFadeContainer->setLayout(splitLayout);
cardLayout = new FlowLayout();
cardLayout->setSizeConstraint(QLayout::SetMinimumSize);
cardLayout->setContentsMargins(0, 0, 0, 0);
cardLayout->setSpacing(0);
cardContainer->setLayout(cardLayout);
// setMinimumSize(0, 0);
}
TierRow::~TierRow()
{
qDebug() << "Row destructor called " << id();
if (idMap.erase(id()) == 0)
{
qDebug() << "Row id not found during destructor";
}
}
void TierRow::addCard(TierCard* card)
{
cardContainer->layout()->addWidget(card);
}
// TierCard* TierRow::takeCard(uint32_t id)
// {
// for (auto i : cardContainer->children())
// }
void TierRow::setColor(QColor color)
{
_color = color;
titleCard->setColor(color);
auto str = makeBgColorString(color);
setStyleSheet(str);
}
QColor TierRow::color()
{
return _color;
}
void TierRow::setText(QString text)
{
titleCard->setText(text);
}
QString TierRow::text()
{
return titleCard->text();
}
uint32_t TierRow::id()
{
return titleCard->id();
}
void TierRow::resizeEvent(QResizeEvent* event)
{
this->QWidget::resizeEvent(event);
recalcMaxHeight();
}
void TierRow::recalcMaxHeight()
{
setMaximumHeight(cardLayout->totalMinimumHeightForWidth(cardContainer->width()));
}
TierRow* TierRow::create(QWidget* parent)
{
TierRow* row;
for (IdType id = 1;; id++)
{
if (idMap.find(id) == idMap.end())
{
row = new TierRow(id, parent);
idMap[id] = row;
return row;
}
}
}
TierRow* TierRow::getFromId(IdType id)
{
auto iter = idMap.find(id);
if (iter == idMap.end())
{
return nullptr;
}
return iter->second;
}
void TierRow::dropEvent(QDropEvent *event)
{
qDebug() << "drop event";
//card dragged to this row
if (event->mimeData()->hasFormat(TierCard::MimeType))
{
if (event->proposedAction() == Qt::MoveAction)
{
auto data = event->mimeData()->data(TierCard::MimeType);
QDataStream stream(&data, QIODevice::ReadOnly);
TierCard::IdType cardId;
uint dataLen = 0;
stream.readRawData(reinterpret_cast<char*>(&cardId), dataLen);
auto card = TierCard::getFromId(cardId);
addCard(card);
event->acceptProposedAction();
}
else
{
event->ignore();
}
}
//image(s) dragged to make new card(s)
else if (event->mimeData()->hasImage())
{
}
}
void TierRow::dragEnterEvent(QDragEnterEvent *event)
{
qDebug() << "drag enter event";
if (event->mimeData()->hasFormat(TierCard::MimeType))
{
if (event->proposedAction() == Qt::MoveAction)
{
event->setDropAction(Qt::MoveAction);
event->accept(cardContainer->rect());
}
else
{
event->setDropAction(Qt::MoveAction);
event->accept(cardContainer->geometry());
}
}
else if (event->mimeData()->hasImage())
{
event->setDropAction(Qt::CopyAction);
event->accept();
}
else {
event->ignore();
}
}
void TierRow::dragMoveEvent(QDragMoveEvent *event)
{
qDebug() << "drag move event";
if (event->mimeData()->hasFormat(TierCard::MimeType))
{
if (event->proposedAction() == Qt::MoveAction)
{
event->acceptProposedAction();
}
else
{
event->setDropAction(Qt::MoveAction);
event->accept(cardContainer->geometry());
}
}
else if (event->mimeData()->hasImage())
{
event->setDropAction(Qt::CopyAction);
event->accept();
}
else {
event->ignore();
}
}

51
tierrow.hpp Normal file
View File

@@ -0,0 +1,51 @@
#ifndef TIERROW_HPP
#define TIERROW_HPP
#include "tiercard.hpp"
#include "tierrowtitlecard.hpp"
#include "flowlayout.h"
#include <QWidget>
#include <QDrag>
class TierRow : public QWidget
{
Q_OBJECT
public:
using IdType = TierRowTitleCard::IdType;
static TierRow* create(QWidget* parent = nullptr);
static TierRow* getFromId(IdType id);
~TierRow();
void addCard(TierCard* card);
TierCard* takeCard(uint32_t id);
void setColor(QColor color);
QColor color();
void setText(QString text);
QString text();
uint32_t id();
protected:
void resizeEvent(QResizeEvent* event) override;
// void mousePressEvent(QMouseEvent* event) override;
void dropEvent(QDropEvent *event) override;
void dragEnterEvent(QDragEnterEvent *event) override;
void dragMoveEvent(QDragMoveEvent *event) override;
private:
explicit TierRow(IdType id, QWidget* parent = nullptr);
TierRowTitleCard* titleCard;
QWidget* bgFadeContainer;
QWidget* cardContainer;
QLayout* cardLayout;
QColor _color;
void recalcMaxHeight();
inline static std::unordered_map<IdType, TierRow*> idMap;
public slots:
void cardResize(QRect newSize);
signals:
};
#endif // TIERROW_HPP

42
tierrowtitlecard.cpp Normal file
View File

@@ -0,0 +1,42 @@
#include "tierrowtitlecard.hpp"
#include "fullsizelayout.hpp"
#include "utils.hpp"
#include <QFrame>
TierRowTitleCard::TierRowTitleCard(IdType id, QWidget *parent)
: QFrame{parent}
{
this->setFrameStyle(QFrame::Box | QFrame::Plain);
auto layout = new FullSizeLayout();
titleLabel = new QLabel();
idLabel = new QLabel();
layout->addWidget(titleLabel);
layout->addWidget(idLabel);
setLayout(layout);
}
QString TierRowTitleCard::text() const
{
return titleLabel->text();
}
QColor TierRowTitleCard::color() const
{
return _color;
}
void TierRowTitleCard::setText(QString& str)
{
titleLabel->setText(str);
}
void TierRowTitleCard::setColor(QColor color)
{
_color = color;
setStyleSheet(makeBgColorString(color));
}
uint32_t TierRowTitleCard::id() const
{
return static_cast<uint32_t>(idLabel->text().toUInt());
}

27
tierrowtitlecard.hpp Normal file
View File

@@ -0,0 +1,27 @@
#ifndef TIERROWTITLECARD_HPP
#define TIERROWTITLECARD_HPP
#include <QWidget>
#include <QLabel>
class TierRowTitleCard : public QFrame
{
Q_OBJECT
public:
using IdType = uint32_t;
explicit TierRowTitleCard(IdType id, QWidget *parent = nullptr);
void setColor(QColor color);
QColor color() const;
void setText(QString& text);
QString text() const;
uint32_t id() const;
private:
QColor _color;
QLabel* titleLabel;
QLabel* idLabel;
signals:
};
#endif // TIERROWTITLECARD_HPP

56
utils.hpp Normal file
View File

@@ -0,0 +1,56 @@
#ifndef UTILS_HPP
#define UTILS_HPP
#include "tierrow.hpp"
#include <QWidget>
#include <QString>
//change this stupid name
inline void callOnMeAndChildren(QObject* obj, void (*func)(QObject*))
{
func(obj);
for (auto w : obj->children())
{
callOnMeAndChildren(w, func);
}
}
template <typename T>
void callOnMeAndChildren(QObject* obj, void (*func)(T*))
{
if (auto casted = dynamic_cast<T*>(obj))
{
func(casted);
}
for (auto w : obj->children())
{
callOnMeAndChildren(w, func);
}
}
inline QString makeBgColorString(QColor color)
{
return QString("background-color: rgba(%1,%2,%3,%4)")
.arg(QString::number(color.red()),
QString::number(color.green()),
QString::number(color.blue()),
QString::number(color.alphaF()));
}
template <typename T>
T* findParentOfType(QObject* obj)
{
auto parent = obj->parent();
if (!parent)
return nullptr;
else if (auto asT = dynamic_cast<T*>(parent))
{
return asT;
}
else
{
return findParentOfType<T>(parent);
}
}
#endif // UTILS_HPP