structurelibraryview.cpp 6.19 KB
Newer Older
1
2
3
4
5
6
7
8
9
10
/*
 * <32021 by Stellaris. Copying Art is an act of love. Love is not subject to law.
 */
#include "structurelibraryview.hpp"
#include "ui_structurelibraryview.h"

#include "structurereader.hpp"

#include <QFile>
#include <QTextStream>
Yann Boucher's avatar
Yann Boucher committed
11
12
#include <QPixmap>
#include <QImage>
13
14
15
#include <QDrag>
#include <QMimeData>

16
17
18
19
20
21
22
23
24
25
26
#include <QDebug>

StructureLibraryView::StructureLibraryView(QWidget *parent) :
    QFrame(parent),
    ui(new Ui::StructureLibraryView)
{
    ui->setupUi(this);

    load_structures();

    connect(ui->tree, &QTreeWidget::itemClicked, this, &StructureLibraryView::update_info);
27
    connect(ui->tree, &QTreeWidget::itemDoubleClicked, this, &StructureLibraryView::create_drag);
28
    connect(ui->button_copy, &QPushButton::pressed, this, &StructureLibraryView::copy_button_clicked);
29
    connect(&m_watcher, &QFileSystemWatcher::directoryChanged, this, [this](const QString&)
30
31
32
    {
        load_structures();
    });
33
34
35
36
37
38
39
}

StructureLibraryView::~StructureLibraryView()
{
    delete ui;
}

40
void StructureLibraryView::update_cell_pixel_size(unsigned size)
41
{
42
    m_cell_pixel_size = size;
43
44
}

45
46
void StructureLibraryView::load_structures()
{
47
48
49
    // clear the previously watched directories
    m_watcher.removePaths(m_watcher.directories());

50
51
    QTreeWidgetItem* pattern_list = add_directory_contents(QDir("patterns/"));
    pattern_list->setText(0, "Patterns");
52
    ui->tree->clear();
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
    ui->tree->addTopLevelItem(pattern_list);
    pattern_list->setExpanded(true);
}

QTreeWidgetItem *StructureLibraryView::add_directory_contents(const QDir &dir)
{
    QTreeWidgetItem* root = new QTreeWidgetItem;

    QFileInfoList dirs = dir.entryInfoList(QStringList(), QDir::Dirs | QDir::NoDotAndDotDot);
    Q_FOREACH (QFileInfo dir, dirs)
    {
        QTreeWidgetItem *child = add_directory_contents(QDir(dir.absoluteFilePath()));
        // empty directory
        if (child->childCount() == 0)
            continue;

        child->setText(0, dir.fileName());
        root->addChild(child);
    }

    QFileInfoList files = dir.entryInfoList(QStringList() << "*.rle" << "*.json", QDir::Files);
    Q_FOREACH (QFileInfo file, files)
    {
        Structure s;
77
        bool valid = try_load_structure(file.absoluteFilePath(), s);
78
79
80
81
82
83
84
85
86
87
88
        if (!valid)
            continue;

        QTreeWidgetItem *child = new QTreeWidgetItem();
        child->setText(0, file.fileName());
        // data is the complete filepath of the structure, store it so it can be easily accessed when an item is selected
        child->setData(0, Qt::UserRole, file.absoluteFilePath());

        root->addChild(child);
    }

89
90
91
    // register this directory for filesystem watching
    m_watcher.addPath(dir.absolutePath());

92
93
94
    return root;
}

95
bool StructureLibraryView::try_load_structure(const QString &filename, Structure &s)
96
{
97
    try
98
    {
99
100
        s = load_structure(filename.toStdString());
        return true;
101
    }
102
    catch (const StructureReaderException& e)
103
    {
104
        //qDebug() << "StructureReaderException : " << e.what() << "\n";
105
        return false;
106
    }
107
108
}

Yann Boucher's avatar
Yann Boucher committed
109
110
111
112
113
void StructureLibraryView::update_preview(const Structure &s)
{
    QPixmap pix;

    /** to check wether load ok */
114
    if(pix.convertFromImage(create_preview_image(s, Qt::white))){
Yann Boucher's avatar
Yann Boucher committed
115
116
117
118
119
120
        /** scale pixmap to fit in label'size and keep ratio of pixmap */
        pix = pix.scaled(ui->preview->size() - 2*QSize(ui->preview->lineWidth(), ui->preview->lineWidth()),Qt::KeepAspectRatio);
        ui->preview->setPixmap(pix);
    }
}

121
122
123
124
125
126
127
128
129
130
QImage StructureLibraryView::create_preview_image(const Structure &s, QColor background)
{
    QImage img(s.width(), s.height(), QImage::Format_ARGB32);
    img.fill(background);
    for (const auto& cell : s)
        img.setPixelColor(cell.first.x, cell.first.y, QColor(Qt::black));

    return img;
}

131
132
133
134
135
void StructureLibraryView::update_info(QTreeWidgetItem *item, int column)
{
    (void)column;

    Structure s;
136
    if (!try_load_structure(item->data(0, Qt::UserRole).toString(), s))
137
138
139
140
    {
        ui->button_copy->setEnabled(false);
        return;
    }
Yann Boucher's avatar
Yann Boucher committed
141
142
143
144
    if (!s.title.empty())
        ui->struct_title->setText(QString::fromStdString(s.title));
    else
    {
Yann Boucher's avatar
Yann Boucher committed
145
        QString filename = QFileInfo(item->data(0, Qt::UserRole).toString()).baseName();
Yann Boucher's avatar
Yann Boucher committed
146
147
148
149
        if (!filename.isEmpty()) // failsafe, in case it actually is empty
            filename.replace(0, 1, filename[0].toUpper());
        ui->struct_title->setText(filename);
    }
150
151
152
    ui->struct_author->setText(QString::fromStdString(s.author));
    ui->struct_date->setText(QString::fromStdString(s.date));
    ui->struct_desc->setPlainText(QString::fromStdString(s.desc));
Yann Boucher's avatar
Yann Boucher committed
153
154
155
    ui->struct_size->setText(QString::number(s.width()) + "x" + QString::number(s.height()));

    update_preview(s);
156
157
158
159
160
161
162
163
164
165
166
167

    ui->button_copy->setEnabled(true);
}

void StructureLibraryView::copy_button_clicked()
{
    if (ui->tree->selectedItems().size() == 0)
        return;

    QTreeWidgetItem* item = ui->tree->selectedItems()[0];

    Structure s;
168
    if (!try_load_structure(item->data(0, Qt::UserRole).toString(), s))
169
170
171
172
        return;

    emit structure_copied(s);
}
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191

void StructureLibraryView::create_drag(QTreeWidgetItem *item, int column)
{
    (void)column;

    Structure s;
    if (!try_load_structure(item->data(0, Qt::UserRole).toString(), s))
    {
        ui->button_copy->setEnabled(false);
        return;
    }

    QDrag* drag = new QDrag(this);
    QMimeData* mimeData = new QMimeData;

    QString filename = QFileInfo(item->data(0, Qt::UserRole).toString()).absoluteFilePath();
    QPixmap pix;
    QImage img = create_preview_image(s, Qt::transparent);
    pix.convertFromImage(img);
192
193
194
195
196
197
198
199
200
201
202
203


    QSize target_size;
    // set target size so that a single cell has the same size as the grid's cells
    target_size = QSize(s.width(), s.height()) * m_cell_pixel_size;
    // Have a maximum size to avoid drawing huge megastructures all over the screen
    const int max_size = 600;
    if (target_size.width() >= max_size)
        target_size.setWidth(max_size);
    if (target_size.height() >= max_size)
        target_size.setHeight(max_size);
    pix = pix.scaled(target_size, Qt::KeepAspectRatio);
204
205
206
207

    mimeData->setText(filename);
    drag->setMimeData(mimeData);
    drag->setPixmap(pix);
208
    drag->setHotSpot(QPoint(m_cell_pixel_size/2, m_cell_pixel_size/2));
209
210
211

    drag->exec(Qt::CopyAction);
}