From fac2260a01ebc50c47bc03cc5a7dd8c8f4c693a7 Mon Sep 17 00:00:00 2001 From: Ikatono Date: Mon, 20 May 2024 03:23:01 -0500 Subject: [PATCH] bunch of stuff. very basic drag/drop now working --- .gitignore | 75 ++++++++++++++ CMakeLists.txt | 84 ++++++++++++++++ aspectratiopixmaplabel.cpp | 36 +++++++ aspectratiopixmaplabel.hpp | 23 +++++ flowlayout.cpp | 154 +++++++++++++++++++++++++++++ flowlayout.h | 41 ++++++++ flowlayout.pro | 11 +++ fullsizelayout.cpp | 91 +++++++++++++++++ fullsizelayout.hpp | 28 ++++++ main.cpp | 141 ++++++++++++++++++++++++++ mainwindow.cpp | 15 +++ mainwindow.h | 23 +++++ mainwindow.ui | 31 ++++++ myflowlayout.cpp | 109 ++++++++++++++++++++ myflowlayout.hpp | 36 +++++++ rowholder.cpp | 19 ++++ rowholder.hpp | 25 +++++ settings.cpp | 5 + settings.hpp | 15 +++ tiercard.cpp | 185 ++++++++++++++++++++++++++++++++++ tiercard.hpp | 49 +++++++++ tiercardlayout.cpp | 30 ++++++ tiercardlayout.hpp | 31 ++++++ tierrow.cpp | 198 +++++++++++++++++++++++++++++++++++++ tierrow.hpp | 51 ++++++++++ tierrowtitlecard.cpp | 42 ++++++++ tierrowtitlecard.hpp | 27 +++++ utils.hpp | 56 +++++++++++ 28 files changed, 1631 insertions(+) create mode 100644 .gitignore create mode 100644 CMakeLists.txt create mode 100644 aspectratiopixmaplabel.cpp create mode 100644 aspectratiopixmaplabel.hpp create mode 100644 flowlayout.cpp create mode 100644 flowlayout.h create mode 100644 flowlayout.pro create mode 100644 fullsizelayout.cpp create mode 100644 fullsizelayout.hpp create mode 100644 main.cpp create mode 100644 mainwindow.cpp create mode 100644 mainwindow.h create mode 100644 mainwindow.ui create mode 100644 myflowlayout.cpp create mode 100644 myflowlayout.hpp create mode 100644 rowholder.cpp create mode 100644 rowholder.hpp create mode 100644 settings.cpp create mode 100644 settings.hpp create mode 100644 tiercard.cpp create mode 100644 tiercard.hpp create mode 100644 tiercardlayout.cpp create mode 100644 tiercardlayout.hpp create mode 100644 tierrow.cpp create mode 100644 tierrow.hpp create mode 100644 tierrowtitlecard.cpp create mode 100644 tierrowtitlecard.hpp create mode 100644 utils.hpp diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..28db11b --- /dev/null +++ b/.gitignore @@ -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 diff --git a/CMakeLists.txt b/CMakeLists.txt new file mode 100644 index 0000000..e0e6566 --- /dev/null +++ b/CMakeLists.txt @@ -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() diff --git a/aspectratiopixmaplabel.cpp b/aspectratiopixmaplabel.cpp new file mode 100644 index 0000000..d1a4d7d --- /dev/null +++ b/aspectratiopixmaplabel.cpp @@ -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()); +} diff --git a/aspectratiopixmaplabel.hpp b/aspectratiopixmaplabel.hpp new file mode 100644 index 0000000..a7b2232 --- /dev/null +++ b/aspectratiopixmaplabel.hpp @@ -0,0 +1,23 @@ +#ifndef ASPECTRATIOPIXMAPLABEL_HPP +#define ASPECTRATIOPIXMAPLABEL_HPP + +#include +#include +#include + +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 diff --git a/flowlayout.cpp b/flowlayout.cpp new file mode 100644 index 0000000..9ce3c4e --- /dev/null +++ b/flowlayout.cpp @@ -0,0 +1,154 @@ +// Copyright (C) 2016 The Qt Company Ltd. +// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR BSD-3-Clause + +#include + +#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(parent); + return pw->style()->pixelMetric(pm, nullptr, pw); + } else { + return static_cast(parent)->spacing(); + } +} diff --git a/flowlayout.h b/flowlayout.h new file mode 100644 index 0000000..3c5291b --- /dev/null +++ b/flowlayout.h @@ -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 +#include +#include +//! [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 itemList; + int m_hSpace; + int m_vSpace; +}; +//! [0] + +#endif // FLOWLAYOUT_H diff --git a/flowlayout.pro b/flowlayout.pro new file mode 100644 index 0000000..a0cfd40 --- /dev/null +++ b/flowlayout.pro @@ -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 diff --git a/fullsizelayout.cpp b/fullsizelayout.cpp new file mode 100644 index 0000000..af9f6f2 --- /dev/null +++ b/fullsizelayout.cpp @@ -0,0 +1,91 @@ +#include "fullsizelayout.hpp" +#include "qdebug.h" +#include "qwidget.h" +#include + +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(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); +} diff --git a/fullsizelayout.hpp b/fullsizelayout.hpp new file mode 100644 index 0000000..cbd63d8 --- /dev/null +++ b/fullsizelayout.hpp @@ -0,0 +1,28 @@ +#ifndef FULLSIZELAYOUT_HPP +#define FULLSIZELAYOUT_HPP + +#include + +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 itemList; +}; + +#endif // FULLSIZELAYOUT_HPP diff --git a/main.cpp b/main.cpp new file mode 100644 index 0000000..0ac1f55 --- /dev/null +++ b/main.cpp @@ -0,0 +1,141 @@ +#include "mainwindow.h" +#include "tiercard.hpp" +#include "tierrow.hpp" +#include "tiercardlayout.hpp" +#include "utils.hpp" +#include "rowholder.hpp" + +#include +#include +#include +#include +#include +#include +#include + +// 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(&row, [](TierRow* obj) + // { + // auto wid = dynamic_cast(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(); +} diff --git a/mainwindow.cpp b/mainwindow.cpp new file mode 100644 index 0000000..83e32a9 --- /dev/null +++ b/mainwindow.cpp @@ -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; +} diff --git a/mainwindow.h b/mainwindow.h new file mode 100644 index 0000000..f7a3da3 --- /dev/null +++ b/mainwindow.h @@ -0,0 +1,23 @@ +#ifndef MAINWINDOW_H +#define MAINWINDOW_H + +#include + +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 diff --git a/mainwindow.ui b/mainwindow.ui new file mode 100644 index 0000000..b07f62d --- /dev/null +++ b/mainwindow.ui @@ -0,0 +1,31 @@ + + + MainWindow + + + + 0 + 0 + 800 + 600 + + + + MainWindow + + + + + + 0 + 0 + 800 + 25 + + + + + + + + diff --git a/myflowlayout.cpp b/myflowlayout.cpp new file mode 100644 index 0000000..5feba13 --- /dev/null +++ b/myflowlayout.cpp @@ -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; +// } diff --git a/myflowlayout.hpp b/myflowlayout.hpp new file mode 100644 index 0000000..4a91699 --- /dev/null +++ b/myflowlayout.hpp @@ -0,0 +1,36 @@ +// #ifndef MYFLOWLAYOUT_HPP +// #define MYFLOWLAYOUT_HPP + +// #include +// #include + +// 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 itemList; +// int hSpace; +// int vSpace; +// }; + +// #endif // MYFLOWLAYOUT_HPP diff --git a/rowholder.cpp b/rowholder.cpp new file mode 100644 index 0000000..23840f3 --- /dev/null +++ b/rowholder.cpp @@ -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() +{ + +} diff --git a/rowholder.hpp b/rowholder.hpp new file mode 100644 index 0000000..5af5089 --- /dev/null +++ b/rowholder.hpp @@ -0,0 +1,25 @@ +#ifndef ROWHOLDER_HPP +#define ROWHOLDER_HPP + +#include "tierrow.hpp" + +#include +#include +#include +#include + +class RowHolder : public QFrame +{ + Q_OBJECT +public: + using IdType = uint32_t; + RowHolder(); + ~RowHolder(); + void addRow(TierRow* row); + + +private: + QVBoxLayout* _layout; +}; + +#endif // ROWHOLDER_HPP diff --git a/settings.cpp b/settings.cpp new file mode 100644 index 0000000..a83f6d4 --- /dev/null +++ b/settings.cpp @@ -0,0 +1,5 @@ +#include "settings.hpp" + +Settings::Settings(QObject *parent) + : QObject{parent} +{} diff --git a/settings.hpp b/settings.hpp new file mode 100644 index 0000000..d68a30e --- /dev/null +++ b/settings.hpp @@ -0,0 +1,15 @@ +#ifndef SETTINGS_HPP +#define SETTINGS_HPP + +#include + +class Settings : public QObject +{ + Q_OBJECT +public: + explicit Settings(QObject *parent = nullptr); + +signals: +}; + +#endif // SETTINGS_HPP diff --git a/tiercard.cpp b/tiercard.cpp new file mode 100644 index 0000000..a9b4b84 --- /dev/null +++ b/tiercard.cpp @@ -0,0 +1,185 @@ +#include "tiercard.hpp" +#include "fullsizelayout.hpp" +#include "qmimedata.h" +#include "utils.hpp" + +#include + +// 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(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(&_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); +} diff --git a/tiercard.hpp b/tiercard.hpp new file mode 100644 index 0000000..2139a3a --- /dev/null +++ b/tiercard.hpp @@ -0,0 +1,49 @@ +#ifndef TIERCARD_H +#define TIERCARD_H + +#include "aspectratiopixmaplabel.hpp" + +#include +#include +#include + +#include + +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 idMap; + +signals: +}; + +#endif // TIERCARD_H diff --git a/tiercardlayout.cpp b/tiercardlayout.cpp new file mode 100644 index 0000000..7409e4e --- /dev/null +++ b/tiercardlayout.cpp @@ -0,0 +1,30 @@ +// #include "tiercardlayout.hpp" +// #include + +// 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(); +// } diff --git a/tiercardlayout.hpp b/tiercardlayout.hpp new file mode 100644 index 0000000..35cc1ee --- /dev/null +++ b/tiercardlayout.hpp @@ -0,0 +1,31 @@ +// #ifndef TIERCARDLAYOUT_HPP +// #define TIERCARDLAYOUT_HPP + +// #include +// #include + +// 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 itemList; +// QLabel* image; +// QLabel* text; +// QLabel* id; +// }; + +// #endif // TIERCARDLAYOUT_HPP diff --git a/tierrow.cpp b/tierrow.cpp new file mode 100644 index 0000000..5a368a9 --- /dev/null +++ b/tierrow.cpp @@ -0,0 +1,198 @@ +#include "tierrow.hpp" +#include "fullsizelayout.hpp" +#include "qmimedata.h" +#include "utils.hpp" + +#include + +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(&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(); + } +} diff --git a/tierrow.hpp b/tierrow.hpp new file mode 100644 index 0000000..c745a29 --- /dev/null +++ b/tierrow.hpp @@ -0,0 +1,51 @@ +#ifndef TIERROW_HPP +#define TIERROW_HPP + +#include "tiercard.hpp" +#include "tierrowtitlecard.hpp" +#include "flowlayout.h" + +#include +#include + +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 idMap; + +public slots: + void cardResize(QRect newSize); + +signals: + +}; + +#endif // TIERROW_HPP diff --git a/tierrowtitlecard.cpp b/tierrowtitlecard.cpp new file mode 100644 index 0000000..f1e95f7 --- /dev/null +++ b/tierrowtitlecard.cpp @@ -0,0 +1,42 @@ +#include "tierrowtitlecard.hpp" +#include "fullsizelayout.hpp" +#include "utils.hpp" + +#include + +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(idLabel->text().toUInt()); +} diff --git a/tierrowtitlecard.hpp b/tierrowtitlecard.hpp new file mode 100644 index 0000000..c6ca041 --- /dev/null +++ b/tierrowtitlecard.hpp @@ -0,0 +1,27 @@ +#ifndef TIERROWTITLECARD_HPP +#define TIERROWTITLECARD_HPP + +#include +#include + +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 diff --git a/utils.hpp b/utils.hpp new file mode 100644 index 0000000..88f4ad7 --- /dev/null +++ b/utils.hpp @@ -0,0 +1,56 @@ +#ifndef UTILS_HPP +#define UTILS_HPP + +#include "tierrow.hpp" + +#include +#include + +//change this stupid name +inline void callOnMeAndChildren(QObject* obj, void (*func)(QObject*)) +{ + func(obj); + for (auto w : obj->children()) + { + callOnMeAndChildren(w, func); + } +} +template +void callOnMeAndChildren(QObject* obj, void (*func)(T*)) +{ + if (auto casted = dynamic_cast(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 +T* findParentOfType(QObject* obj) +{ + auto parent = obj->parent(); + if (!parent) + return nullptr; + else if (auto asT = dynamic_cast(parent)) + { + return asT; + } + else + { + return findParentOfType(parent); + } +} + +#endif // UTILS_HPP